]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #88661 - est31:typo_fix_in_test, r=joshtriplett
authorRyan Levick <rylev@users.noreply.github.com>
Mon, 6 Sep 2021 10:38:56 +0000 (12:38 +0200)
committerGitHub <noreply@github.com>
Mon, 6 Sep 2021 10:38:56 +0000 (12:38 +0200)
Correct typo

found while addressing reviewer remarks for #88316

1915 files changed:
Cargo.lock
RELEASES.md
compiler/rustc_arena/src/lib.rs
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/attr/mod.rs
compiler/rustc_ast/src/lib.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/util/classify.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/src/asm.rs
compiler/rustc_ast_lowering/src/block.rs [new file with mode: 0644]
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_ast_lowering/src/item.rs
compiler/rustc_ast_lowering/src/lib.rs
compiler/rustc_ast_lowering/src/pat.rs
compiler/rustc_ast_lowering/src/path.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/mod.rs
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/deriving/debug.rs
compiler/rustc_builtin_macros/src/deriving/mod.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_builtin_macros/src/proc_macro_harness.rs
compiler/rustc_codegen_cranelift/src/archive.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
compiler/rustc_codegen_cranelift/src/driver/aot.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/lib.rs
compiler/rustc_codegen_llvm/Cargo.toml
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/allocator.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/back/archive.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/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
compiler/rustc_codegen_llvm/src/intrinsic.rs
compiler/rustc_codegen_llvm/src/lib.rs
compiler/rustc_codegen_llvm/src/llvm_util.rs
compiler/rustc_codegen_llvm/src/mono_item.rs
compiler/rustc_codegen_llvm/src/type_of.rs
compiler/rustc_codegen_llvm/src/va_arg.rs
compiler/rustc_codegen_ssa/Cargo.toml
compiler/rustc_codegen_ssa/src/back/archive.rs
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/base.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/mir/analyze.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/mod.rs
compiler/rustc_codegen_ssa/src/mir/operand.rs
compiler/rustc_codegen_ssa/src/mir/place.rs
compiler/rustc_codegen_ssa/src/mir/rvalue.rs
compiler/rustc_codegen_ssa/src/mono_item.rs
compiler/rustc_codegen_ssa/src/traits/backend.rs
compiler/rustc_data_structures/Cargo.toml
compiler/rustc_data_structures/src/flock.rs
compiler/rustc_data_structures/src/functor.rs
compiler/rustc_data_structures/src/owning_ref/mod.rs
compiler/rustc_data_structures/src/thin_vec.rs
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0152.md
compiler/rustc_error_codes/src/error_codes/E0671.md
compiler/rustc_error_codes/src/error_codes/E0741.md
compiler/rustc_error_codes/src/error_codes/E0770.md
compiler/rustc_error_codes/src/error_codes/E0771.md
compiler/rustc_error_codes/src/error_codes/E0785.md [new file with mode: 0644]
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/emitter.rs
compiler/rustc_errors/src/json.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/build.rs
compiler/rustc_expand/src/config.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/lib.rs
compiler/rustc_expand/src/mbe/macro_rules.rs
compiler/rustc_expand/src/module.rs
compiler/rustc_expand/src/placeholders.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/removed.rs
compiler/rustc_hir/src/arena.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/stable_hash_impls.rs
compiler/rustc_hir/src/target.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/src/persist/dirty_clean.rs
compiler/rustc_index/src/bit_set.rs
compiler/rustc_index/src/bit_set/tests.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_infer/src/infer/canonical/query_response.rs
compiler/rustc_infer/src/infer/combine.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/freshen.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/outlives/verify.rs
compiler/rustc_infer/src/infer/resolve.rs
compiler/rustc_infer/src/traits/error_reporting/mod.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/context.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/levels.rs
compiler/rustc_lint/src/lib.rs
compiler/rustc_lint/src/noop_method_call.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/hir/map/collector.rs
compiler/rustc_middle/src/hir/map/mod.rs
compiler/rustc_middle/src/hir/mod.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/lint.rs
compiler/rustc_middle/src/middle/region.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/mod.rs
compiler/rustc_middle/src/mir/visit.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/ty/codec.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/consts/kind.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/erase_regions.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/flags.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/outlives.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/structural_impls.rs
compiler/rustc_middle/src/ty/sty.rs
compiler/rustc_middle/src/ty/subst.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_middle/src/ty/walk.rs
compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs
compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
compiler/rustc_mir/src/borrow_check/region_infer/values.rs
compiler/rustc_mir/src/borrow_check/type_check/canonical.rs
compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs
compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs
compiler/rustc_mir/src/borrow_check/type_check/mod.rs
compiler/rustc_mir/src/const_eval/eval_queries.rs
compiler/rustc_mir/src/interpret/cast.rs
compiler/rustc_mir/src/interpret/eval_context.rs
compiler/rustc_mir/src/interpret/intrinsics.rs
compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs
compiler/rustc_mir/src/interpret/operand.rs
compiler/rustc_mir/src/interpret/operator.rs
compiler/rustc_mir/src/interpret/place.rs
compiler/rustc_mir/src/interpret/step.rs
compiler/rustc_mir/src/interpret/terminator.rs
compiler/rustc_mir/src/interpret/util.rs
compiler/rustc_mir/src/interpret/validity.rs
compiler/rustc_mir/src/monomorphize/collector.rs
compiler/rustc_mir/src/monomorphize/polymorphize.rs
compiler/rustc_mir/src/shim.rs
compiler/rustc_mir/src/transform/check_consts/check.rs
compiler/rustc_mir/src/transform/check_consts/qualifs.rs
compiler/rustc_mir/src/transform/const_prop.rs
compiler/rustc_mir/src/transform/function_item_references.rs
compiler/rustc_mir/src/transform/generator.rs
compiler/rustc_mir/src/transform/inline.rs
compiler/rustc_mir/src/transform/inline/cycle.rs
compiler/rustc_mir/src/transform/mod.rs
compiler/rustc_mir/src/transform/promote_consts.rs
compiler/rustc_mir/src/util/alignment.rs
compiler/rustc_mir/src/util/pretty.rs
compiler/rustc_mir_build/src/build/expr/into.rs
compiler/rustc_mir_build/src/build/matches/mod.rs
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/build/scope.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_mir_build/src/thir/pattern/check_match.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_build/src/thir/visit.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/attr.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/mod.rs
compiler/rustc_parse/src/parser/nonterminal.rs
compiler/rustc_parse/src/parser/stmt.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_parse/src/validate_attr.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/diagnostic_items.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_passes/src/hir_stats.rs
compiler/rustc_passes/src/lang_items.rs
compiler/rustc_passes/src/layout_test.rs
compiler/rustc_passes/src/lib_features.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/reachable.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_privacy/Cargo.toml
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/src/keys.rs
compiler/rustc_query_impl/src/lib.rs
compiler/rustc_query_impl/src/plumbing.rs
compiler/rustc_query_impl/src/util.rs [new file with mode: 0644]
compiler/rustc_query_system/src/query/job.rs
compiler/rustc_query_system/src/query/mod.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/late.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/late/lifetimes.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_resolve/src/macros.rs
compiler/rustc_save_analysis/src/dump_visitor.rs
compiler/rustc_save_analysis/src/lib.rs
compiler/rustc_save_analysis/src/sig.rs
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/src/edition.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_symbol_mangling/Cargo.toml
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/lib.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_target/src/abi/call/aarch64.rs
compiler/rustc_target/src/abi/call/amdgpu.rs
compiler/rustc_target/src/abi/call/arm.rs
compiler/rustc_target/src/abi/call/mips.rs
compiler/rustc_target/src/abi/call/mips64.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/abi/call/powerpc64.rs
compiler/rustc_target/src/abi/call/riscv.rs
compiler/rustc_target/src/abi/call/s390x.rs
compiler/rustc_target/src/abi/call/sparc.rs
compiler/rustc_target/src/abi/call/sparc64.rs
compiler/rustc_target/src/abi/call/wasm.rs
compiler/rustc_target/src/abi/call/x86.rs
compiler/rustc_target/src/abi/call/x86_64.rs
compiler/rustc_target/src/abi/mod.rs
compiler/rustc_target/src/asm/mod.rs
compiler/rustc_target/src/asm/powerpc.rs
compiler/rustc_target/src/asm/s390x.rs [new file with mode: 0644]
compiler/rustc_target/src/lib.rs
compiler/rustc_target/src/spec/abi.rs
compiler/rustc_target/src/spec/apple_base.rs
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
compiler/rustc_trait_selection/src/infer.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/coherence.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.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/mod.rs
compiler/rustc_trait_selection/src/traits/object_safety.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/confirmation.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_trait_selection/src/traits/structural_match.rs
compiler/rustc_trait_selection/src/traits/util.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/src/chalk/lowering.rs
compiler/rustc_traits/src/lib.rs
compiler/rustc_traits/src/type_op.rs
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_type_ir/src/lib.rs
compiler/rustc_typeck/Cargo.toml
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/bounds.rs
compiler/rustc_typeck/src/check/_match.rs
compiler/rustc_typeck/src/check/cast.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/coercion.rs
compiler/rustc_typeck/src/check/compare_method.rs
compiler/rustc_typeck/src/check/dropck.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fallback.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
compiler/rustc_typeck/src/check/method/prelude2021.rs
compiler/rustc_typeck/src/check/method/probe.rs
compiler/rustc_typeck/src/check/method/suggest.rs
compiler/rustc_typeck/src/check/mod.rs
compiler/rustc_typeck/src/check/op.rs
compiler/rustc_typeck/src/check/pat.rs
compiler/rustc_typeck/src/check/regionck.rs
compiler/rustc_typeck/src/check/upvar.rs
compiler/rustc_typeck/src/check/wfcheck.rs
compiler/rustc_typeck/src/check/writeback.rs
compiler/rustc_typeck/src/check_unused.rs
compiler/rustc_typeck/src/coherence/inherent_impls.rs
compiler/rustc_typeck/src/coherence/mod.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
compiler/rustc_typeck/src/constrained_generic_params.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
compiler/rustc_typeck/src/impl_wf_check.rs
compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/outlives/implicit_infer.rs
library/alloc/src/collections/btree/map.rs
library/alloc/src/collections/btree/map/tests.rs
library/alloc/src/collections/btree/set.rs
library/alloc/src/collections/btree/set/tests.rs
library/alloc/src/collections/linked_list.rs
library/alloc/src/collections/mod.rs
library/alloc/src/raw_vec.rs
library/alloc/src/rc.rs
library/alloc/src/sync.rs
library/alloc/tests/boxed.rs
library/alloc/tests/const_fns.rs
library/core/src/array/iter.rs
library/core/src/array/mod.rs
library/core/src/bool.rs
library/core/src/cell.rs
library/core/src/char/methods.rs
library/core/src/cmp.rs
library/core/src/fmt/mod.rs
library/core/src/iter/adapters/intersperse.rs
library/core/src/iter/adapters/mod.rs
library/core/src/iter/mod.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lib.rs
library/core/src/num/dec2flt/mod.rs
library/core/src/num/int_log10.rs
library/core/src/num/int_macros.rs
library/core/src/num/mod.rs
library/core/src/num/saturating.rs [new file with mode: 0644]
library/core/src/num/uint_macros.rs
library/core/src/ops/control_flow.rs
library/core/src/ops/mod.rs
library/core/src/option.rs
library/core/src/ptr/mod.rs
library/core/src/result.rs
library/core/src/slice/sort.rs
library/core/src/str/mod.rs
library/core/src/task/poll.rs
library/core/src/time.rs
library/core/tests/cell.rs
library/core/tests/lib.rs
library/core/tests/num/int_log.rs
library/core/tests/num/int_macros.rs
library/core/tests/num/uint_macros.rs
library/core/tests/slice.rs
library/std/Cargo.toml
library/std/src/env.rs
library/std/src/ffi/c_str.rs
library/std/src/ffi/os_str.rs
library/std/src/io/buffered/bufwriter.rs
library/std/src/io/buffered/mod.rs
library/std/src/io/error.rs
library/std/src/io/mod.rs
library/std/src/lib.rs
library/std/src/net/tcp.rs
library/std/src/net/tcp/tests.rs
library/std/src/net/udp.rs
library/std/src/num.rs
library/std/src/os/raw/mod.rs
library/std/src/os/unix/fs.rs
library/std/src/os/windows/fs.rs
library/std/src/primitive_docs.rs
library/std/src/sys/hermit/net.rs
library/std/src/sys/sgx/net.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/l4re.rs
library/std/src/sys/unix/net.rs
library/std/src/sys/unix/stack_overflow.rs
library/std/src/sys/unsupported/net.rs
library/std/src/sys/wasi/net.rs
library/std/src/sys/windows/args.rs
library/std/src/sys/windows/args/tests.rs
library/std/src/sys/windows/c.rs
library/std/src/sys/windows/net.rs
library/std/src/sys/windows/stdio.rs
library/std/src/sys_common/net.rs
library/std/src/time.rs
library/stdarch
library/unwind/build.rs
library/unwind/src/lib.rs
library/unwind/src/libunwind.rs
src/bootstrap/bootstrap.py
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/download-ci-llvm-stamp
src/bootstrap/flags.rs
src/bootstrap/native.rs
src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
src/ci/docker/scripts/sccache.sh
src/ci/pgo.sh
src/ci/scripts/install-sccache.sh
src/doc/book
src/doc/edition-guide
src/doc/embedded-book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/rustc/src/command-line-arguments.md
src/doc/rustc/src/lints/levels.md
src/doc/unstable-book/src/compiler-flags/force-warn.md [deleted file]
src/doc/unstable-book/src/library-features/asm.md
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/config.rs
src/librustdoc/core.rs
src/librustdoc/doctest.rs
src/librustdoc/doctree.rs
src/librustdoc/fold.rs
src/librustdoc/html/format.rs
src/librustdoc/html/length_limit.rs [new file with mode: 0644]
src/librustdoc/html/length_limit/tests.rs [new file with mode: 0644]
src/librustdoc/html/markdown.rs
src/librustdoc/html/markdown/tests.rs
src/librustdoc/html/mod.rs
src/librustdoc/html/render/context.rs
src/librustdoc/html/render/mod.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/render/span_map.rs
src/librustdoc/html/render/write_shared.rs
src/librustdoc/html/sources.rs
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/json/conversions.rs
src/librustdoc/json/mod.rs
src/librustdoc/lib.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/collect_intra_doc_links/early.rs [new file with mode: 0644]
src/librustdoc/passes/mod.rs
src/librustdoc/passes/stripper.rs
src/librustdoc/visit_ast.rs
src/llvm-project
src/rustdoc-json-types/lib.rs
src/test/assembly/asm/powerpc-types.rs
src/test/assembly/asm/s390x-types.rs [new file with mode: 0644]
src/test/codegen/asm-powerpc-clobbers.rs [new file with mode: 0644]
src/test/codegen/uninit-consts-allow-partially-uninit.rs [new file with mode: 0644]
src/test/codegen/uninit-consts.rs [new file with mode: 0644]
src/test/debuginfo/function-call.rs
src/test/debuginfo/function-names.rs
src/test/debuginfo/step-into-match.rs [new file with mode: 0644]
src/test/incremental/const-generics/hash-tyvid-regression-1.rs
src/test/incremental/const-generics/hash-tyvid-regression-1.stderr [deleted file]
src/test/incremental/const-generics/hash-tyvid-regression-2.rs
src/test/incremental/const-generics/hash-tyvid-regression-2.stderr [deleted file]
src/test/incremental/const-generics/hash-tyvid-regression-3.rs
src/test/incremental/const-generics/hash-tyvid-regression-3.stderr [deleted file]
src/test/incremental/const-generics/hash-tyvid-regression-4.rs
src/test/incremental/const-generics/hash-tyvid-regression-4.stderr [deleted file]
src/test/incremental/const-generics/issue-61338.rs
src/test/incremental/const-generics/issue-61516.rs
src/test/incremental/const-generics/issue-62536.rs
src/test/incremental/const-generics/issue-64087.rs
src/test/incremental/const-generics/issue-65623.rs
src/test/incremental/const-generics/issue-68477.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-2.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-3.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-82034.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-1.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-2.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-85031-3.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-86953.rs
src/test/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-88022.rs
src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
src/test/mir-opt/bool_compare.opt1.InstCombine.diff
src/test/mir-opt/bool_compare.opt2.InstCombine.diff
src/test/mir-opt/bool_compare.opt3.InstCombine.diff
src/test/mir-opt/bool_compare.opt4.InstCombine.diff
src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff
src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff
src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
src/test/mir-opt/const_prop/switch_int.main.SimplifyBranches-after-const-prop.diff
src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyBranches-final.after.diff
src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
src/test/mir-opt/early_otherwise_branch_noopt.noopt2.EarlyOtherwiseBranch.diff
src/test/mir-opt/equal_true.opt.InstCombine.diff
src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
src/test/mir-opt/inline/inline_diverging.g.Inline.diff
src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
src/test/mir-opt/issue_49232.main.mir_map.0.mir
src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
src/test/mir-opt/match_false_edges.full_tested_match2.PromoteTemps.before.mir
src/test/mir-opt/match_false_edges.main.PromoteTemps.before.mir
src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/not_equal_false.opt.InstCombine.diff
src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff
src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir
src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
src/test/mir-opt/simple_match.match_bool.mir_map.0.32bit.mir
src/test/mir-opt/simple_match.match_bool.mir_map.0.64bit.mir
src/test/mir-opt/simplify_arm.id.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_arm.id.SimplifyBranchSame.diff
src/test/mir-opt/simplify_arm.id_result.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_arm.id_result.SimplifyBranchSame.diff
src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.32bit.diff
src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.64bit.diff
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
src/test/mir-opt/simplify_if.main.SimplifyBranches-after-const-prop.diff
src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
src/test/mir-opt/simplify_match.main.ConstProp.diff
src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_asm.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_asm_2.main.UnreachablePropagation.diff
src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.32bit.diff
src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.64bit.diff
src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.uses_inline_crate.txt
src/test/run-make-fulldeps/doctests-keep-binaries/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/doctests-keep-binaries/t.rs [new file with mode: 0644]
src/test/run-make-fulldeps/remap-path-prefix/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs [new file with mode: 0644]
src/test/run-make/incr-foreign-head-span/Makefile [new file with mode: 0644]
src/test/run-make/incr-foreign-head-span/first_crate.rs [new file with mode: 0644]
src/test/run-make/incr-foreign-head-span/second_crate.rs [new file with mode: 0644]
src/test/run-make/unstable-flag-required/Makefile
src/test/run-make/unstable-flag-required/force-warn.stderr [deleted file]
src/test/run-make/wasm-spurious-import/Makefile [new file with mode: 0644]
src/test/run-make/wasm-spurious-import/main.rs [new file with mode: 0644]
src/test/run-make/wasm-spurious-import/verify.js [new file with mode: 0644]
src/test/rustdoc-gui/ayu-code-tag-colors.goml [deleted file]
src/test/rustdoc-gui/code-color.goml [new file with mode: 0644]
src/test/rustdoc-gui/font-weight.goml
src/test/rustdoc-gui/implementors.goml
src/test/rustdoc-gui/src/lib2/implementors/lib.rs
src/test/rustdoc-gui/src/lib2/lib.rs
src/test/rustdoc-gui/src/test_docs/lib.rs
src/test/rustdoc-gui/toggle-implementors.goml [new file with mode: 0644]
src/test/rustdoc-json/enums/variant_struct.rs [new file with mode: 0644]
src/test/rustdoc-json/enums/variant_tuple_struct.rs [new file with mode: 0644]
src/test/rustdoc-json/structs/with_primitives.rs
src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs [new file with mode: 0644]
src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr [new file with mode: 0644]
src/test/rustdoc-ui/auxiliary/panic-item.rs [new file with mode: 0644]
src/test/rustdoc-ui/bounded-hr-lifetime.rs [new file with mode: 0644]
src/test/rustdoc-ui/bounded-hr-lifetime.stderr [new file with mode: 0644]
src/test/rustdoc-ui/deny-missing-docs-macro.stderr
src/test/rustdoc-ui/unused-extern-crate.rs [new file with mode: 0644]
src/test/rustdoc/auxiliary/issue-66159-1.rs [deleted file]
src/test/rustdoc/const-generics/add-impl.rs
src/test/rustdoc/const-generics/const-evaluatable-checked.rs [deleted file]
src/test/rustdoc/const-generics/const-generic-slice.rs
src/test/rustdoc/const-generics/const-impl.rs
src/test/rustdoc/const-generics/generic_const_exprs.rs [new file with mode: 0644]
src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
src/test/rustdoc/intra-doc/auxiliary/pub-struct.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/extern-reference-link.rs [new file with mode: 0644]
src/test/rustdoc/intra-doc/issue-66159.rs [new file with mode: 0644]
src/test/rustdoc/issue-66159.rs [deleted file]
src/test/rustdoc/macro-document-private-duplicate.rs [new file with mode: 0644]
src/test/rustdoc/macro-document-private.rs [new file with mode: 0644]
src/test/rustdoc/macro-indirect-use.rs [new file with mode: 0644]
src/test/rustdoc/macro-private-not-documented.rs [new file with mode: 0644]
src/test/rustdoc/trait-impl-items-links-and-anchors.rs
src/test/rustfix/closure-immutable-outer-variable.fixed [deleted file]
src/test/rustfix/closure-immutable-outer-variable.rs [deleted file]
src/test/rustfix/empty-no-fixes.fixed [deleted file]
src/test/rustfix/empty-no-fixes.rs [deleted file]
src/test/rustfix/empty-no-fixes.rs.fixed [deleted file]
src/test/rustfix/issue-45562.fixed [deleted file]
src/test/rustfix/issue-45562.rs [deleted file]
src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed [deleted file]
src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs [deleted file]
src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed [deleted file]
src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs [deleted file]
src/test/rustfix/main-no-fixes.fixed [deleted file]
src/test/rustfix/main-no-fixes.rs [deleted file]
src/test/rustfix/main-no-fixes.rs.fixed [deleted file]
src/test/rustfix/missing-comma-in-match.fixed [deleted file]
src/test/rustfix/missing-comma-in-match.rs [deleted file]
src/test/rustfix/str-as-char.fixed [deleted file]
src/test/rustfix/str-as-char.rs [deleted file]
src/test/rustfix/tuple-float-index.fixed [deleted file]
src/test/rustfix/tuple-float-index.rs [deleted file]
src/test/ui-fulldeps/pprust-expr-roundtrip.rs
src/test/ui/abi/unsupported.aarch64.stderr
src/test/ui/abi/unsupported.arm.stderr [new file with mode: 0644]
src/test/ui/abi/unsupported.i686.stderr
src/test/ui/abi/unsupported.rs
src/test/ui/abi/unsupported.x64.stderr
src/test/ui/array-slice-vec/match_arr_unknown_len.rs
src/test/ui/array-slice-vec/match_arr_unknown_len.stderr
src/test/ui/asm/named-asm-labels.rs
src/test/ui/asm/named-asm-labels.stderr
src/test/ui/asm/type-check-1.stderr
src/test/ui/associated-consts/associated-const-type-parameter-arrays.stderr
src/test/ui/associated-item/associated-item-duplicate-bounds.stderr
src/test/ui/associated-type-bounds/ambiguous-associated-type2.stderr
src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr
src/test/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr
src/test/ui/associated-type-bounds/issue-83017.rs
src/test/ui/associated-type-bounds/issue-83017.stderr [deleted file]
src/test/ui/associated-types/higher-ranked-projection.bad.nll.stderr
src/test/ui/associated-types/higher-ranked-projection.bad.stderr
src/test/ui/associated-types/hr-associated-type-bound-1.rs
src/test/ui/associated-types/hr-associated-type-bound-1.stderr
src/test/ui/associated-types/hr-associated-type-bound-2.rs
src/test/ui/associated-types/hr-associated-type-bound-2.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-1.rs
src/test/ui/associated-types/hr-associated-type-bound-param-1.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-2.rs
src/test/ui/associated-types/hr-associated-type-bound-param-2.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-3.rs
src/test/ui/associated-types/hr-associated-type-bound-param-3.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-4.rs
src/test/ui/associated-types/hr-associated-type-bound-param-4.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-5.rs
src/test/ui/associated-types/hr-associated-type-bound-param-5.stderr
src/test/ui/associated-types/hr-associated-type-bound-param-6.rs
src/test/ui/associated-types/hr-associated-type-bound-param-6.stderr
src/test/ui/associated-types/hr-associated-type-projection-1.rs
src/test/ui/associated-types/hr-associated-type-projection-1.stderr
src/test/ui/associated-types/normalization-generality-2.rs [new file with mode: 0644]
src/test/ui/ast-json/ast-json-noexpand-output.stdout
src/test/ui/ast-json/ast-json-output.stdout
src/test/ui/async-await/edition-deny-async-fns-2015.stderr
src/test/ui/async-await/issues/issue-78654.rs
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/binding/const-param.full.stderr [deleted file]
src/test/ui/binding/const-param.min.stderr [deleted file]
src/test/ui/binding/const-param.rs
src/test/ui/binding/const-param.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-anon-fields-variant.rs
src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.rs
src/test/ui/borrowck/borrowck-describe-lvalue.stderr
src/test/ui/borrowck/borrowck-match-already-borrowed.rs
src/test/ui/borrowck/borrowck-match-already-borrowed.stderr
src/test/ui/borrowck/issue-27282-move-match-input-into-guard.rs
src/test/ui/borrowck/issue-27282-move-match-input-into-guard.stderr
src/test/ui/borrowck/issue-64453.stderr
src/test/ui/borrowck/mut-borrow-of-mut-ref.rs
src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr
src/test/ui/closures/2229_closure_analysis/issue-87097.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/issue-87097.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/issue-87426.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/issue-87987.rs
src/test/ui/closures/2229_closure_analysis/issue-87987.stderr
src/test/ui/closures/2229_closure_analysis/issue-87988.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/issue_88118.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/move_closure.rs
src/test/ui/closures/2229_closure_analysis/move_closure.stderr
src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs [deleted file]
src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr [deleted file]
src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.rs
src/test/ui/closures/2229_closure_analysis/run_pass/destructure_patterns.stderr
src/test/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs [new file with mode: 0644]
src/test/ui/closures/2229_closure_analysis/run_pass/move_closure.rs
src/test/ui/closures/issue-41366.rs
src/test/ui/closures/issue-41366.stderr [deleted file]
src/test/ui/closures/issue-87814-1.rs [new file with mode: 0644]
src/test/ui/closures/issue-87814-2.rs [new file with mode: 0644]
src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
src/test/ui/coherence/coherence_inherent.stderr
src/test/ui/coherence/coherence_inherent_cc.stderr
src/test/ui/coherence/issue-85026.rs [new file with mode: 0644]
src/test/ui/coherence/issue-85026.stderr [new file with mode: 0644]
src/test/ui/const-generics/apit-with-const-param.rs
src/test/ui/const-generics/argument_order.full.stderr
src/test/ui/const-generics/argument_order.min.stderr
src/test/ui/const-generics/argument_order.rs
src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr [deleted file]
src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr [deleted file]
src/test/ui/const-generics/array-size-in-generic-struct-param.rs [deleted file]
src/test/ui/const-generics/array-wrapper-struct-ctor.rs
src/test/ui/const-generics/associated-type-bound-fail.full.stderr [deleted file]
src/test/ui/const-generics/associated-type-bound-fail.min.stderr [deleted file]
src/test/ui/const-generics/associated-type-bound-fail.rs
src/test/ui/const-generics/associated-type-bound-fail.stderr [new file with mode: 0644]
src/test/ui/const-generics/associated-type-bound.rs
src/test/ui/const-generics/auxiliary/const_generic_lib.rs
src/test/ui/const-generics/auxiliary/crayte.rs
src/test/ui/const-generics/auxiliary/generics_of_parent.rs
src/test/ui/const-generics/auxiliary/generics_of_parent_impl_trait.rs
src/test/ui/const-generics/backcompat/trait-resolution-breakage.rs [new file with mode: 0644]
src/test/ui/const-generics/backcompat/unevaluated-consts.rs [new file with mode: 0644]
src/test/ui/const-generics/broken-mir-1.rs
src/test/ui/const-generics/broken-mir-2.rs
src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
src/test/ui/const-generics/closing-args-token.full.stderr [deleted file]
src/test/ui/const-generics/closing-args-token.min.stderr [deleted file]
src/test/ui/const-generics/closing-args-token.rs [deleted file]
src/test/ui/const-generics/coerce_unsized_array.rs
src/test/ui/const-generics/concrete-const-as-fn-arg.rs
src/test/ui/const-generics/concrete-const-impl-method.rs
src/test/ui/const-generics/condition-in-trait-const-arg.rs
src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs
src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs
src/test/ui/const-generics/const-arg-in-const-arg.min.stderr
src/test/ui/const-generics/const-arg-in-const-arg.rs
src/test/ui/const-generics/const-arg-in-fn.rs
src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr [deleted file]
src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr [deleted file]
src/test/ui/const-generics/const-arg-type-arg-misordered.rs
src/test/ui/const-generics/const-arg-type-arg-misordered.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr [deleted file]
src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr [deleted file]
src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs
src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-argument-if-length.full.stderr
src/test/ui/const-generics/const-argument-if-length.min.stderr
src/test/ui/const-generics/const-argument-if-length.rs
src/test/ui/const-generics/const-argument-non-static-lifetime.rs
src/test/ui/const-generics/const-expression-parameter.full.stderr [deleted file]
src/test/ui/const-generics/const-expression-parameter.min.stderr [deleted file]
src/test/ui/const-generics/const-expression-parameter.rs [deleted file]
src/test/ui/const-generics/const-fn-with-const-param.rs
src/test/ui/const-generics/const-generic-array-wrapper.rs [deleted file]
src/test/ui/const-generics/const-generic-type_name.rs
src/test/ui/const-generics/const-param-after-const-literal-arg.rs
src/test/ui/const-generics/const-param-before-other-params.full.stderr
src/test/ui/const-generics/const-param-before-other-params.min.stderr
src/test/ui/const-generics/const-param-before-other-params.rs
src/test/ui/const-generics/const-param-elided-lifetime.full.stderr
src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
src/test/ui/const-generics/const-param-elided-lifetime.rs
src/test/ui/const-generics/const-param-from-outer-fn.full.stderr [deleted file]
src/test/ui/const-generics/const-param-from-outer-fn.min.stderr [deleted file]
src/test/ui/const-generics/const-param-from-outer-fn.rs [deleted file]
src/test/ui/const-generics/const-param-hygiene.rs [deleted file]
src/test/ui/const-generics/const-param-in-async.rs
src/test/ui/const-generics/const-param-in-trait.rs [deleted file]
src/test/ui/const-generics/const-param-shadowing.rs [deleted file]
src/test/ui/const-generics/const-param-shadowing.stderr [deleted file]
src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
src/test/ui/const-generics/const-param-type-depends-on-const-param.rs
src/test/ui/const-generics/const-param-type-depends-on-type-param.rs
src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr [deleted file]
src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr [deleted file]
src/test/ui/const-generics/const-parameter-uppercase-lint.rs
src/test/ui/const-generics/const-parameter-uppercase-lint.stderr [new file with mode: 0644]
src/test/ui/const-generics/const-types.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/closures.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/closures.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/division.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/drop_impl.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/evaluated-to-ambig.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/impl-bounds.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/infer-too-generic.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/less_than.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/simple.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/unop.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/unused_expr.rs [deleted file]
src/test/ui/const-generics/const_evaluatable_checked/unused_expr.stderr [deleted file]
src/test/ui/const-generics/const_trait_fn-issue-88433.rs [new file with mode: 0644]
src/test/ui/const-generics/core-types.rs
src/test/ui/const-generics/cross_crate_complex.rs
src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
src/test/ui/const-generics/defaults/cec-concrete-default.rs [deleted file]
src/test/ui/const-generics/defaults/cec-concrete-default.stderr [deleted file]
src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs [deleted file]
src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr [deleted file]
src/test/ui/const-generics/defaults/cec-generic-default.rs [deleted file]
src/test/ui/const-generics/defaults/cec-generic-default.stderr [deleted file]
src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
src/test/ui/const-generics/defaults/complex-unord-param.rs
src/test/ui/const-generics/defaults/const-default.rs
src/test/ui/const-generics/defaults/default-annotation.rs
src/test/ui/const-generics/defaults/default-on-impl.full.stderr [deleted file]
src/test/ui/const-generics/defaults/default-on-impl.min.stderr [deleted file]
src/test/ui/const-generics/defaults/default-on-impl.rs
src/test/ui/const-generics/defaults/default-on-impl.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/external.rs
src/test/ui/const-generics/defaults/generic-expr-default-concrete.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/generic-expr-default.rs [new file with mode: 0644]
src/test/ui/const-generics/defaults/generic-expr-default.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
src/test/ui/const-generics/defaults/intermixed-lifetime.rs
src/test/ui/const-generics/defaults/mismatch.full.stderr [deleted file]
src/test/ui/const-generics/defaults/mismatch.min.stderr [deleted file]
src/test/ui/const-generics/defaults/mismatch.rs
src/test/ui/const-generics/defaults/mismatch.stderr [new file with mode: 0644]
src/test/ui/const-generics/defaults/needs-feature.min.stderr
src/test/ui/const-generics/defaults/needs-feature.none.stderr [deleted file]
src/test/ui/const-generics/defaults/needs-feature.rs
src/test/ui/const-generics/defaults/simple-defaults.rs
src/test/ui/const-generics/defaults/type-default-const-param-name.rs
src/test/ui/const-generics/defaults/wrong-order.full.stderr [deleted file]
src/test/ui/const-generics/defaults/wrong-order.min.stderr [deleted file]
src/test/ui/const-generics/defaults/wrong-order.rs
src/test/ui/const-generics/defaults/wrong-order.stderr [new file with mode: 0644]
src/test/ui/const-generics/derive-debug-array-wrapper.rs [deleted file]
src/test/ui/const-generics/diagnostics.rs [deleted file]
src/test/ui/const-generics/diagnostics.stderr [deleted file]
src/test/ui/const-generics/different_byref.full.stderr [deleted file]
src/test/ui/const-generics/different_byref.min.stderr [deleted file]
src/test/ui/const-generics/different_byref.rs [deleted file]
src/test/ui/const-generics/different_byref_simple.full.stderr [deleted file]
src/test/ui/const-generics/different_byref_simple.min.stderr [deleted file]
src/test/ui/const-generics/different_byref_simple.rs [deleted file]
src/test/ui/const-generics/different_generic_args.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_generic_args.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/different_generic_args.rs [new file with mode: 0644]
src/test/ui/const-generics/different_generic_args_array.rs [new file with mode: 0644]
src/test/ui/const-generics/different_generic_args_array.stderr [new file with mode: 0644]
src/test/ui/const-generics/dont-evaluate-array-len-on-err-1.rs
src/test/ui/const-generics/dyn-supertraits.rs
src/test/ui/const-generics/early/closing-args-token.rs [new file with mode: 0644]
src/test/ui/const-generics/early/closing-args-token.stderr [new file with mode: 0644]
src/test/ui/const-generics/early/const-expression-parameter.rs [new file with mode: 0644]
src/test/ui/const-generics/early/const-expression-parameter.stderr [new file with mode: 0644]
src/test/ui/const-generics/early/const-param-from-outer-fn.rs [new file with mode: 0644]
src/test/ui/const-generics/early/const-param-from-outer-fn.stderr [new file with mode: 0644]
src/test/ui/const-generics/early/const-param-hygiene.rs [new file with mode: 0644]
src/test/ui/const-generics/early/const-param-shadowing.rs [new file with mode: 0644]
src/test/ui/const-generics/early/const-param-shadowing.stderr [new file with mode: 0644]
src/test/ui/const-generics/early/invalid-const-arguments.rs [new file with mode: 0644]
src/test/ui/const-generics/early/invalid-const-arguments.stderr [new file with mode: 0644]
src/test/ui/const-generics/early/macro_rules-braces.rs [new file with mode: 0644]
src/test/ui/const-generics/early/macro_rules-braces.stderr [new file with mode: 0644]
src/test/ui/const-generics/exhaustive-value.full.stderr [deleted file]
src/test/ui/const-generics/exhaustive-value.min.stderr [deleted file]
src/test/ui/const-generics/exhaustive-value.rs
src/test/ui/const-generics/exhaustive-value.stderr [new file with mode: 0644]
src/test/ui/const-generics/fn-const-param-call.rs
src/test/ui/const-generics/fn-const-param-infer.rs
src/test/ui/const-generics/fn-taking-const-generic-array.rs [deleted file]
src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr [deleted file]
src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr [deleted file]
src/test/ui/const-generics/forbid-non-structural_match-types.rs
src/test/ui/const-generics/forbid-non-structural_match-types.stderr [new file with mode: 0644]
src/test/ui/const-generics/foreign-item-const-parameter.full.stderr [deleted file]
src/test/ui/const-generics/foreign-item-const-parameter.min.stderr [deleted file]
src/test/ui/const-generics/foreign-item-const-parameter.rs
src/test/ui/const-generics/foreign-item-const-parameter.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr [deleted file]
src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr [deleted file]
src/test/ui/const-generics/generic-function-call-in-array-length.rs [deleted file]
src/test/ui/const-generics/generic-param-mismatch.full.stderr [deleted file]
src/test/ui/const-generics/generic-param-mismatch.min.stderr [deleted file]
src/test/ui/const-generics/generic-param-mismatch.rs
src/test/ui/const-generics/generic-param-mismatch.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic-sum-in-array-length.full.stderr [deleted file]
src/test/ui/const-generics/generic-sum-in-array-length.min.stderr [deleted file]
src/test/ui/const-generics/generic-sum-in-array-length.rs [deleted file]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/associated-const.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/associated-consts.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/closures.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/closures.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/cross_crate.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/different-fn.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/different-fn.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/division.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/drop_impl.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/fn_call.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/from-sig.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/function-call.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/function-call.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/impl-bounds.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/infer-too-generic.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-62504.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-69654.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72787.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-73899.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-74634.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-76595.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-80742.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-83765.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-84408.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-85848.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/less_than.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/let-bindings.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/needs_where_clause.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/needs_where_clause.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/no_where_clause.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/no_where_clause.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/object-safety-ok.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/simple_fail.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unop.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unused_expr.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr [new file with mode: 0644]
src/test/ui/const-generics/impl-const-generic-struct.rs
src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr [deleted file]
src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr [deleted file]
src/test/ui/const-generics/impl-trait-with-const-arguments.rs
src/test/ui/const-generics/impl-trait-with-const-arguments.stderr [new file with mode: 0644]
src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr [deleted file]
src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr [deleted file]
src/test/ui/const-generics/incorrect-number-of-const-args.rs
src/test/ui/const-generics/incorrect-number-of-const-args.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr [deleted file]
src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr [deleted file]
src/test/ui/const-generics/infer/cannot-infer-const-args.rs
src/test/ui/const-generics/infer/cannot-infer-const-args.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/method-chain.full.stderr [deleted file]
src/test/ui/const-generics/infer/method-chain.min.stderr [deleted file]
src/test/ui/const-generics/infer/method-chain.rs
src/test/ui/const-generics/infer/method-chain.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/one-param-uninferred.full.stderr [deleted file]
src/test/ui/const-generics/infer/one-param-uninferred.min.stderr [deleted file]
src/test/ui/const-generics/infer/one-param-uninferred.rs
src/test/ui/const-generics/infer/one-param-uninferred.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer/uninferred-consts.full.stderr [deleted file]
src/test/ui/const-generics/infer/uninferred-consts.min.stderr [deleted file]
src/test/ui/const-generics/infer/uninferred-consts.rs
src/test/ui/const-generics/infer/uninferred-consts.stderr [new file with mode: 0644]
src/test/ui/const-generics/infer_arg_from_pat.rs
src/test/ui/const-generics/infer_arr_len_from_pat.rs
src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs
src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr [deleted file]
src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
src/test/ui/const-generics/intrinsics-type_name-as-const-argument.rs
src/test/ui/const-generics/invalid-enum.rs
src/test/ui/const-generics/issues/auxiliary/const_generic_issues_lib.rs
src/test/ui/const-generics/issues/auxiliary/impl-const.rs
src/test/ui/const-generics/issues/issue-56445-1.full.stderr
src/test/ui/const-generics/issues/issue-56445-1.min.stderr
src/test/ui/const-generics/issues/issue-56445-1.rs
src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
src/test/ui/const-generics/issues/issue-61336-1.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61336-1.rs
src/test/ui/const-generics/issues/issue-61336-2.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61336-2.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61336-2.rs
src/test/ui/const-generics/issues/issue-61336-2.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61336.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61336.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61336.rs
src/test/ui/const-generics/issues/issue-61336.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-61422.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61422.rs
src/test/ui/const-generics/issues/issue-61432.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61432.rs
src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs [deleted file]
src/test/ui/const-generics/issues/issue-61747.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61747.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61747.rs [deleted file]
src/test/ui/const-generics/issues/issue-61935.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61935.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-61935.rs [deleted file]
src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs
src/test/ui/const-generics/issues/issue-62220.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62220.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62220.rs [deleted file]
src/test/ui/const-generics/issues/issue-62456.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62456.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62456.rs [deleted file]
src/test/ui/const-generics/issues/issue-62504.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62504.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62504.rs [deleted file]
src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-62579-no-match.rs [deleted file]
src/test/ui/const-generics/issues/issue-62878.full.stderr
src/test/ui/const-generics/issues/issue-62878.min.stderr
src/test/ui/const-generics/issues/issue-62878.rs
src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs
src/test/ui/const-generics/issues/issue-64494.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-64494.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-64494.rs [deleted file]
src/test/ui/const-generics/issues/issue-64519.rs
src/test/ui/const-generics/issues/issue-64519.stderr [deleted file]
src/test/ui/const-generics/issues/issue-66205.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-66205.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-66205.rs [deleted file]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.rs
src/test/ui/const-generics/issues/issue-66906.rs
src/test/ui/const-generics/issues/issue-67185-1.rs
src/test/ui/const-generics/issues/issue-67185-2.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-67185-2.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-67185-2.rs
src/test/ui/const-generics/issues/issue-67185-2.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-67375.full.stderr
src/test/ui/const-generics/issues/issue-67375.min.stderr
src/test/ui/const-generics/issues/issue-67375.rs
src/test/ui/const-generics/issues/issue-67739.full.stderr
src/test/ui/const-generics/issues/issue-67739.rs
src/test/ui/const-generics/issues/issue-67945-1.full.stderr
src/test/ui/const-generics/issues/issue-67945-1.min.stderr
src/test/ui/const-generics/issues/issue-67945-1.rs
src/test/ui/const-generics/issues/issue-67945-2.full.stderr
src/test/ui/const-generics/issues/issue-67945-2.min.stderr
src/test/ui/const-generics/issues/issue-67945-2.rs
src/test/ui/const-generics/issues/issue-67945-3.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-67945-3.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-67945-3.rs [deleted file]
src/test/ui/const-generics/issues/issue-68104-print-stack-overflow.rs
src/test/ui/const-generics/issues/issue-68366.min.stderr
src/test/ui/const-generics/issues/issue-68366.rs
src/test/ui/const-generics/issues/issue-68596.rs
src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
src/test/ui/const-generics/issues/issue-68615-adt.rs
src/test/ui/const-generics/issues/issue-68615-array.min.stderr
src/test/ui/const-generics/issues/issue-68615-array.rs
src/test/ui/const-generics/issues/issue-68977.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-68977.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-68977.rs [deleted file]
src/test/ui/const-generics/issues/issue-69654-run-pass.rs
src/test/ui/const-generics/issues/issue-69654-run-pass.stderr [deleted file]
src/test/ui/const-generics/issues/issue-69654.rs [deleted file]
src/test/ui/const-generics/issues/issue-69654.stderr [deleted file]
src/test/ui/const-generics/issues/issue-70125-1.rs
src/test/ui/const-generics/issues/issue-70125-2.rs
src/test/ui/const-generics/issues/issue-70167.rs
src/test/ui/const-generics/issues/issue-70180-1-stalled_on.rs
src/test/ui/const-generics/issues/issue-70180-2-stalled_on.rs
src/test/ui/const-generics/issues/issue-70225.rs
src/test/ui/const-generics/issues/issue-70273-assoc-fn.rs
src/test/ui/const-generics/issues/issue-71169.full.stderr
src/test/ui/const-generics/issues/issue-71169.min.stderr
src/test/ui/const-generics/issues/issue-71169.rs
src/test/ui/const-generics/issues/issue-71202.rs
src/test/ui/const-generics/issues/issue-71202.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-71381.rs
src/test/ui/const-generics/issues/issue-71382.rs
src/test/ui/const-generics/issues/issue-71611.rs
src/test/ui/const-generics/issues/issue-71986.rs
src/test/ui/const-generics/issues/issue-72352.rs
src/test/ui/const-generics/issues/issue-72787.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-72787.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-72787.rs [deleted file]
src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs [deleted file]
src/test/ui/const-generics/issues/issue-73120.rs
src/test/ui/const-generics/issues/issue-73260.rs
src/test/ui/const-generics/issues/issue-73260.stderr
src/test/ui/const-generics/issues/issue-73491.min.stderr
src/test/ui/const-generics/issues/issue-73491.rs
src/test/ui/const-generics/issues/issue-73508.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-73508.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-73508.rs [deleted file]
src/test/ui/const-generics/issues/issue-73899.rs [deleted file]
src/test/ui/const-generics/issues/issue-74101.min.stderr
src/test/ui/const-generics/issues/issue-74101.rs
src/test/ui/const-generics/issues/issue-74255.min.stderr
src/test/ui/const-generics/issues/issue-74255.rs
src/test/ui/const-generics/issues/issue-74634.rs [deleted file]
src/test/ui/const-generics/issues/issue-74634.stderr [deleted file]
src/test/ui/const-generics/issues/issue-74906.rs
src/test/ui/const-generics/issues/issue-74950.min.stderr
src/test/ui/const-generics/issues/issue-74950.rs
src/test/ui/const-generics/issues/issue-75047.min.stderr
src/test/ui/const-generics/issues/issue-75047.rs
src/test/ui/const-generics/issues/issue-75299.rs
src/test/ui/const-generics/issues/issue-75763.rs
src/test/ui/const-generics/issues/issue-76595.rs [deleted file]
src/test/ui/const-generics/issues/issue-76595.stderr [deleted file]
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr [deleted file]
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr [deleted file]
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.rs
src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs [deleted file]
src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr [deleted file]
src/test/ui/const-generics/issues/issue-80062.stderr
src/test/ui/const-generics/issues/issue-80375.stderr
src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs [deleted file]
src/test/ui/const-generics/issues/issue-82956.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-82956.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-83765.rs [deleted file]
src/test/ui/const-generics/issues/issue-83765.stderr [deleted file]
src/test/ui/const-generics/issues/issue-84408.rs [deleted file]
src/test/ui/const-generics/issues/issue-84659.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-84659.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-85848.rs [deleted file]
src/test/ui/const-generics/issues/issue-85848.stderr [deleted file]
src/test/ui/const-generics/issues/issue-86530.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86530.stderr [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86535-2.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-86535.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87076.rs
src/test/ui/const-generics/late-bound-vars/in_closure.rs
src/test/ui/const-generics/late-bound-vars/simple.rs
src/test/ui/const-generics/macro_rules-braces.full.stderr [deleted file]
src/test/ui/const-generics/macro_rules-braces.min.stderr [deleted file]
src/test/ui/const-generics/macro_rules-braces.rs [deleted file]
src/test/ui/const-generics/min_const_generics/complex-expression.stderr
src/test/ui/const-generics/min_const_generics/complex-types.stderr
src/test/ui/const-generics/min_const_generics/const_default_first.rs
src/test/ui/const-generics/min_const_generics/const_default_first.stderr
src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.rs
src/test/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr
src/test/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr
src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs
src/test/ui/const-generics/mut-ref-const-param-array.rs [deleted file]
src/test/ui/const-generics/nested-type.min.stderr
src/test/ui/const-generics/nested-type.rs
src/test/ui/const-generics/occurs-check/bind-param.rs
src/test/ui/const-generics/occurs-check/unify-fixpoint.rs
src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr
src/test/ui/const-generics/occurs-check/unify-n-nplusone.rs
src/test/ui/const-generics/occurs-check/unify-n-nplusone.stderr
src/test/ui/const-generics/occurs-check/unused-substs-1.rs
src/test/ui/const-generics/occurs-check/unused-substs-2.rs
src/test/ui/const-generics/occurs-check/unused-substs-3.rs
src/test/ui/const-generics/occurs-check/unused-substs-4.rs
src/test/ui/const-generics/occurs-check/unused-substs-5.rs
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr
src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs
src/test/ui/const-generics/parent_generics_of_encoding.rs
src/test/ui/const-generics/parent_generics_of_encoding_impl_trait.rs
src/test/ui/const-generics/raw-ptr-const-param-deref.rs
src/test/ui/const-generics/raw-ptr-const-param.rs
src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
src/test/ui/const-generics/slice-const-param-mismatch.rs
src/test/ui/const-generics/slice-const-param.min.stderr [deleted file]
src/test/ui/const-generics/slice-const-param.rs
src/test/ui/const-generics/sneaky-array-repeat-expr.rs [new file with mode: 0644]
src/test/ui/const-generics/sneaky-array-repeat-expr.stderr [new file with mode: 0644]
src/test/ui/const-generics/std/const-generics-range.min.stderr
src/test/ui/const-generics/std/const-generics-range.rs
src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr [deleted file]
src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr [deleted file]
src/test/ui/const-generics/struct-with-invalid-const-param.rs
src/test/ui/const-generics/struct-with-invalid-const-param.stderr
src/test/ui/const-generics/trait-const-args.rs
src/test/ui/const-generics/transmute-const-param-static-reference.min.stderr
src/test/ui/const-generics/transmute-const-param-static-reference.rs
src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs
src/test/ui/const-generics/type-after-const-ok.rs
src/test/ui/const-generics/type-dependent/auxiliary/type_dependent_lib.rs
src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
src/test/ui/const-generics/type-dependent/issue-61936.rs
src/test/ui/const-generics/type-dependent/issue-63695.rs
src/test/ui/const-generics/type-dependent/issue-67144-1.rs
src/test/ui/const-generics/type-dependent/issue-67144-2.rs
src/test/ui/const-generics/type-dependent/issue-69816.rs
src/test/ui/const-generics/type-dependent/issue-70217.rs
src/test/ui/const-generics/type-dependent/issue-70507.rs
src/test/ui/const-generics/type-dependent/issue-70586.rs
src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
src/test/ui/const-generics/type-dependent/issue-71348.rs
src/test/ui/const-generics/type-dependent/issue-71382.full.stderr [deleted file]
src/test/ui/const-generics/type-dependent/issue-71382.min.stderr [deleted file]
src/test/ui/const-generics/type-dependent/issue-71382.rs
src/test/ui/const-generics/type-dependent/issue-71382.stderr [new file with mode: 0644]
src/test/ui/const-generics/type-dependent/issue-71805.rs
src/test/ui/const-generics/type-dependent/issue-73730.rs
src/test/ui/const-generics/type-dependent/non-local.rs
src/test/ui/const-generics/type-dependent/qpath.rs
src/test/ui/const-generics/type-dependent/simple.rs
src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr
src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr
src/test/ui/const-generics/type-dependent/type-mismatch.rs
src/test/ui/const-generics/type_mismatch.stderr
src/test/ui/const-generics/type_of_anon_const.rs
src/test/ui/const-generics/types-mismatch-const-args.full.stderr
src/test/ui/const-generics/types-mismatch-const-args.min.stderr
src/test/ui/const-generics/types-mismatch-const-args.rs
src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs
src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs
src/test/ui/const-generics/unknown_adt.full.stderr [deleted file]
src/test/ui/const-generics/unknown_adt.min.stderr [deleted file]
src/test/ui/const-generics/unknown_adt.rs
src/test/ui/const-generics/unknown_adt.stderr [new file with mode: 0644]
src/test/ui/const-generics/unused-const-param.rs
src/test/ui/const-generics/unused_braces.fixed
src/test/ui/const-generics/unused_braces.full.stderr [deleted file]
src/test/ui/const-generics/unused_braces.min.stderr [deleted file]
src/test/ui/const-generics/unused_braces.rs
src/test/ui/const-generics/unused_braces.stderr [new file with mode: 0644]
src/test/ui/const-generics/wf-misc.full.stderr [deleted file]
src/test/ui/const-generics/wf-misc.min.stderr [deleted file]
src/test/ui/const-generics/wf-misc.rs [deleted file]
src/test/ui/const-generics/where-clauses.rs
src/test/ui/const_evaluatable/associated-const.rs [deleted file]
src/test/ui/const_evaluatable/function-call.rs [deleted file]
src/test/ui/const_evaluatable/function-call.stderr [deleted file]
src/test/ui/const_evaluatable/needs_where_clause.rs [deleted file]
src/test/ui/const_evaluatable/needs_where_clause.stderr [deleted file]
src/test/ui/const_evaluatable/no_where_clause.rs [deleted file]
src/test/ui/const_evaluatable/no_where_clause.stderr [deleted file]
src/test/ui/consts/const-eval/infinite_loop.stderr
src/test/ui/consts/const-eval/issue-49296.rs
src/test/ui/consts/const-eval/issue-49296.stderr
src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.mir.stderr
src/test/ui/consts/const-needs_drop-monomorphic.rs
src/test/ui/consts/const-needs_drop-monomorphic.stderr
src/test/ui/consts/const-size_of-cycle.stderr
src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
src/test/ui/consts/issue-44415.stderr
src/test/ui/consts/issue-66693.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
src/test/ui/cycle-trait/cycle-trait-default-type-trait.stderr
src/test/ui/destructuring-assignment/tuple_struct_destructure_fail.stderr
src/test/ui/did_you_mean/issue-31424.stderr
src/test/ui/did_you_mean/issue-34126.stderr
src/test/ui/did_you_mean/issue-40396.stderr
src/test/ui/drop/drop-if-let-binding.rs [new file with mode: 0644]
src/test/ui/drop/dropck_legal_cycles.rs
src/test/ui/dyn-keyword/dyn-angle-brackets.fixed [new file with mode: 0644]
src/test/ui/dyn-keyword/dyn-angle-brackets.rs [new file with mode: 0644]
src/test/ui/dyn-keyword/dyn-angle-brackets.stderr [new file with mode: 0644]
src/test/ui/editions/async-block-2015.rs
src/test/ui/editions/async-block-2015.stderr
src/test/ui/editions/dyn-trait-sugg-2021.rs [new file with mode: 0644]
src/test/ui/editions/dyn-trait-sugg-2021.stderr [new file with mode: 0644]
src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.stderr
src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice.stderr
src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.stderr
src/test/ui/enum/issue-67945-1.stderr
src/test/ui/enum/issue-67945-2.stderr
src/test/ui/error-codes/E0023.stderr
src/test/ui/error-codes/E0152.rs
src/test/ui/error-codes/E0152.stderr
src/test/ui/error-codes/E0730.rs
src/test/ui/error-codes/E0730.stderr
src/test/ui/error-codes/E0771.rs
src/test/ui/error-codes/E0771.stderr
src/test/ui/extern/extern-no-mangle.rs [new file with mode: 0644]
src/test/ui/extern/extern-no-mangle.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-adt_const_params.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-adt_const_params.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-associated_type_bounds.stderr
src/test/ui/feature-gates/feature-gate-const_generics.rs [deleted file]
src/test/ui/feature-gates/feature-gate-const_generics.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-let_else.rs [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-let_else.stderr [new file with mode: 0644]
src/test/ui/generator/yielding-in-match-guards.rs
src/test/ui/generic-associated-types/issue-87429-2.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87429-specialization.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87429-specialization.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87429.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/issue-87748.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/projection-bound-cycle-generic.stderr
src/test/ui/generic-associated-types/projection-bound-cycle.stderr
src/test/ui/generics/param-in-ct-in-ty-param-default.stderr
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs [new file with mode: 0644]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr [new file with mode: 0644]
src/test/ui/hrtb/due-to-where-clause.nll.stderr [deleted file]
src/test/ui/hrtb/hrtb-cache-issue-54302.nll.stderr [deleted file]
src/test/ui/hrtb/hrtb-just-for-static.nll.stderr
src/test/ui/hrtb/issue-62203-hrtb-ice.stderr
src/test/ui/hygiene/generic_params.rs
src/test/ui/hygiene/generic_params.stderr [deleted file]
src/test/ui/hygiene/issue-61574-const-parameters.rs
src/test/ui/hygiene/issue-61574-const-parameters.stderr [deleted file]
src/test/ui/hygiene/no_implicit_prelude.stderr
src/test/ui/hygiene/trait_items.stderr
src/test/ui/impl-trait/auto-trait-leak.stderr
src/test/ui/impl-trait/bound-normalization-fail.stderr
src/test/ui/impl-trait/issue-55872-1.full_tait.stderr [deleted file]
src/test/ui/impl-trait/issues/issue-79099.stderr
src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr [deleted file]
src/test/ui/infinite/infinite-struct.stderr
src/test/ui/infinite/infinite-tag-type-recursion.stderr
src/test/ui/infinite/infinite-trait-alias-recursion.rs [new file with mode: 0644]
src/test/ui/infinite/infinite-trait-alias-recursion.stderr [new file with mode: 0644]
src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs [new file with mode: 0644]
src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr [new file with mode: 0644]
src/test/ui/infinite/infinite-vec-type-recursion.stderr
src/test/ui/inline-const/const-match-pat-generic.rs [new file with mode: 0644]
src/test/ui/inline-const/const-match-pat-generic.stderr [new file with mode: 0644]
src/test/ui/issues/issue-10465.stderr
src/test/ui/issues/issue-17385.rs
src/test/ui/issues/issue-17385.stderr
src/test/ui/issues/issue-20772.stderr
src/test/ui/issues/issue-20825.stderr
src/test/ui/issues/issue-21177.stderr
src/test/ui/issues/issue-34373.stderr
src/test/ui/issues/issue-35570.rs
src/test/ui/issues/issue-35570.stderr [new file with mode: 0644]
src/test/ui/issues/issue-39559.stderr
src/test/ui/issues/issue-43623.rs
src/test/ui/issues/issue-43623.stderr [deleted file]
src/test/ui/issues/issue-44005.rs
src/test/ui/issues/issue-44005.stderr [new file with mode: 0644]
src/test/ui/issues/issue-47486.stderr
src/test/ui/issues/issue-54302.nll.stderr [deleted file]
src/test/ui/issues/issue-57843.nll.stderr [deleted file]
src/test/ui/issues/issue-59508-1.rs
src/test/ui/issues/issue-59508-1.stderr
src/test/ui/issues/issue-60218.stderr
src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
src/test/ui/issues/issue-72574-2.stderr
src/test/ui/issues/issue-83190.rs [new file with mode: 0644]
src/test/ui/iterators/into-iter-on-arrays-2018.rs
src/test/ui/iterators/into-iter-on-arrays-2018.stderr
src/test/ui/iterators/into-iter-on-arrays-lint.stderr
src/test/ui/lang-items/lang-item-correct-generics.rs [new file with mode: 0644]
src/test/ui/lang-items/lang-item-generic-requirements.rs [new file with mode: 0644]
src/test/ui/lang-items/lang-item-generic-requirements.stderr [new file with mode: 0644]
src/test/ui/lang-items/wrong-number-generic-args-add.rs [deleted file]
src/test/ui/lang-items/wrong-number-generic-args-add.stderr [deleted file]
src/test/ui/lang-items/wrong-number-generic-args-index.rs [deleted file]
src/test/ui/lang-items/wrong-number-generic-args-index.stderr [deleted file]
src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs [deleted file]
src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr [deleted file]
src/test/ui/lazy_normalization_consts/issue-47814.rs [deleted file]
src/test/ui/lazy_normalization_consts/issue-57739.rs [deleted file]
src/test/ui/lazy_normalization_consts/issue-57739.stderr [deleted file]
src/test/ui/lazy_normalization_consts/issue-73980.rs [deleted file]
src/test/ui/lazy_normalization_consts/issue-73980.stderr [deleted file]
src/test/ui/lazy_normalization_consts/trait-resolution-breakage.rs [deleted file]
src/test/ui/lazy_normalization_consts/unevaluated-consts.rs [deleted file]
src/test/ui/legacy-const-generics-bad.stderr
src/test/ui/let-else/let-else-bool-binop-init.fixed [new file with mode: 0644]
src/test/ui/let-else/let-else-bool-binop-init.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-bool-binop-init.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-brace-before-else.fixed [new file with mode: 0644]
src/test/ui/let-else/let-else-brace-before-else.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-brace-before-else.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-check.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-check.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-irrefutable.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-irrefutable.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-missing-semicolon.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-missing-semicolon.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-non-diverging.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-non-diverging.stderr [new file with mode: 0644]
src/test/ui/let-else/let-else-run-pass.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-scope.rs [new file with mode: 0644]
src/test/ui/let-else/let-else-scope.stderr [new file with mode: 0644]
src/test/ui/lint/cli-lint-override.rs
src/test/ui/lint/cli-unknown-force-warn.rs
src/test/ui/lint/cli-unknown-force-warn.stderr
src/test/ui/lint/force-warn/allow-warnings.rs
src/test/ui/lint/force-warn/allowed-by-default-lint.rs
src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs
src/test/ui/lint/force-warn/allowed-warn-by-default-lint.rs
src/test/ui/lint/force-warn/cap-lints-allow.rs
src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.rs
src/test/ui/lint/force-warn/deny-by-default-lint.rs
src/test/ui/lint/force-warn/lint-group-allow-warnings.rs
src/test/ui/lint/force-warn/lint-group-allowed-lint-group.rs
src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs
src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs
src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
src/test/ui/lint/lint-level-macro-def-mod.rs [new file with mode: 0644]
src/test/ui/lint/lint-level-macro-def.rs [new file with mode: 0644]
src/test/ui/lint/missing-doc-private-macro.rs
src/test/ui/lint/missing-doc-private-macro.stderr
src/test/ui/lint/outer-forbid.rs
src/test/ui/lint/outer-forbid.stderr
src/test/ui/lint/unused/issue-88519-unused-paren.rs [new file with mode: 0644]
src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
src/test/ui/liveness/liveness-upvars.rs
src/test/ui/liveness/liveness-upvars.stderr
src/test/ui/macros/issue-87877.rs [new file with mode: 0644]
src/test/ui/macros/macro-stability-rpass.rs
src/test/ui/match/match-pattern-field-mismatch.stderr
src/test/ui/mir/issue-75053.in_bindings.stderr [deleted file]
src/test/ui/mir/issue-80742.rs [deleted file]
src/test/ui/mir/issue-80742.stderr [deleted file]
src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr
src/test/ui/nll/borrowed-match-issue-45045.rs
src/test/ui/nll/borrowed-match-issue-45045.stderr
src/test/ui/nll/closure-use-spans.stderr
src/test/ui/nll/issue-51191.stderr
src/test/ui/nll/match-cfg-fake-edges2.rs
src/test/ui/nll/match-cfg-fake-edges2.stderr
src/test/ui/nll/match-on-borrowed.rs
src/test/ui/nll/match-on-borrowed.stderr
src/test/ui/obsolete-in-place/bad.bad.stderr [deleted file]
src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr [new file with mode: 0644]
src/test/ui/panics/issue-47429-short-backtraces.rs
src/test/ui/panics/issue-47429-short-backtraces.run.stderr [deleted file]
src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr [new file with mode: 0644]
src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
src/test/ui/parser/attr.stderr
src/test/ui/parser/bounds-type.rs
src/test/ui/parser/bounds-type.stderr
src/test/ui/parser/doc-comment-in-if-statement.stderr
src/test/ui/parser/inner-attr-after-doc-comment.stderr
src/test/ui/parser/inner-attr.stderr
src/test/ui/parser/issue-10636-1.stderr
src/test/ui/parser/issue-10636-2.stderr
src/test/ui/parser/issue-30318.fixed [new file with mode: 0644]
src/test/ui/parser/issue-30318.rs
src/test/ui/parser/issue-30318.stderr
src/test/ui/parser/issue-45296.rs
src/test/ui/parser/issue-45296.stderr
src/test/ui/parser/issue-58856-1.stderr
src/test/ui/parser/issue-58856-2.stderr
src/test/ui/parser/issue-60075.stderr
src/test/ui/parser/issue-62973.stderr
src/test/ui/parser/issue-63116.stderr
src/test/ui/parser/issue-66357-unexpected-unreachable.stderr
src/test/ui/parser/issue-67377-invalid-syntax-in-enum-discriminant.stderr
src/test/ui/parser/issue-72253.rs
src/test/ui/parser/issue-72253.stderr
src/test/ui/parser/issue-84117.rs
src/test/ui/parser/issue-84117.stderr
src/test/ui/parser/issue-87812-path.rs [new file with mode: 0644]
src/test/ui/parser/issue-87812-path.stderr [new file with mode: 0644]
src/test/ui/parser/issue-87812.rs [new file with mode: 0644]
src/test/ui/parser/issue-87812.stderr [new file with mode: 0644]
src/test/ui/parser/macro-mismatched-delim-brace-paren.stderr
src/test/ui/parser/macro-mismatched-delim-paren-brace.stderr
src/test/ui/parser/macro/issue-37234.stderr
src/test/ui/parser/missing-semicolon.rs
src/test/ui/parser/missing-semicolon.stderr
src/test/ui/parser/parser-recovery-2.stderr
src/test/ui/parser/range-3.rs
src/test/ui/parser/range-3.stderr
src/test/ui/parser/range-4.rs
src/test/ui/parser/range-4.stderr
src/test/ui/parser/stmt_expr_attrs_placement.stderr
src/test/ui/parser/trait-object-delimiters.rs
src/test/ui/parser/trait-object-delimiters.stderr
src/test/ui/parser/unclosed-delimiter-in-dep.stderr
src/test/ui/parser/unclosed_delim_mod.stderr
src/test/ui/parser/use-unclosed-brace.stderr
src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs [new file with mode: 0644]
src/test/ui/pattern/issue-67037-pat-tup-scrut-ty-diff-less-fields.stderr
src/test/ui/pattern/issue-74539.stderr
src/test/ui/pattern/pat-tuple-field-count-cross.rs [new file with mode: 0644]
src/test/ui/pattern/pat-tuple-field-count-cross.stderr [new file with mode: 0644]
src/test/ui/pattern/pat-tuple-overfield.rs
src/test/ui/pattern/pat-tuple-overfield.stderr
src/test/ui/pattern/pat-tuple-underfield.rs
src/test/ui/pattern/pat-tuple-underfield.stderr
src/test/ui/pattern/pattern-error-continue.stderr
src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.rs
src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
src/test/ui/pattern/usefulness/top-level-alternation.rs
src/test/ui/pattern/usefulness/top-level-alternation.stderr
src/test/ui/polymorphization/const_parameters/closures.rs
src/test/ui/polymorphization/const_parameters/closures.stderr
src/test/ui/polymorphization/const_parameters/functions.rs
src/test/ui/polymorphization/const_parameters/functions.stderr
src/test/ui/polymorphization/generators.rs
src/test/ui/polymorphization/generators.stderr
src/test/ui/polymorphization/promoted-function-2.rs
src/test/ui/polymorphization/promoted-function-2.stderr
src/test/ui/proc-macro/attribute-with-error.stderr
src/test/ui/proc-macro/crt-static.rs
src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed [new file with mode: 0644]
src/test/ui/proc-macro/issue-86781-bad-inner-doc.rs
src/test/ui/proc-macro/issue-86781-bad-inner-doc.stderr
src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
src/test/ui/remap-path-prefix.rs [new file with mode: 0644]
src/test/ui/remap-path-prefix.stderr [new file with mode: 0644]
src/test/ui/repeat_count.stderr
src/test/ui/resolve/issue-23305.stderr
src/test/ui/resolve/issue-65035-static-with-parent-generics.rs
src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr
src/test/ui/resolve/resolve-self-in-impl.stderr
src/test/ui/resolve/token-error-correct-2.stderr
src/test/ui/resolve/token-error-correct-3.stderr
src/test/ui/resolve/token-error-correct-4.stderr
src/test/ui/resolve/token-error-correct.stderr
src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.rs
src/test/ui/rfc-2008-non-exhaustive/borrowck-non-exhaustive.stderr
src/test/ui/rfc-2294-if-let-guard/bindings.rs
src/test/ui/rfc-2294-if-let-guard/bindings.stderr
src/test/ui/rfc-2294-if-let-guard/run-pass.rs
src/test/ui/rfc-2294-if-let-guard/typeck.rs
src/test/ui/rfc-2294-if-let-guard/typeck.stderr
src/test/ui/rfc-2294-if-let-guard/warns.rs
src/test/ui/rfc-2294-if-let-guard/warns.stderr
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs
src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
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 [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs [deleted file]
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-trait-bound-opt-out/feature-gate.gated.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs [deleted file]
src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs
src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr
src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/syntax.rs
src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr [new file with mode: 0644]
src/test/ui/rfcs/rfc-1789-as-cell/from-mut.rs
src/test/ui/rust-2018/trait-import-suggestions.stderr
src/test/ui/rust-2021/array-into-iter-ambiguous.fixed [new file with mode: 0644]
src/test/ui/rust-2021/array-into-iter-ambiguous.rs [new file with mode: 0644]
src/test/ui/rust-2021/array-into-iter-ambiguous.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-generic.fixed
src/test/ui/rust-2021/future-prelude-collision-generic.rs
src/test/ui/rust-2021/future-prelude-collision-generic.stderr
src/test/ui/rust-2021/future-prelude-collision-imported.fixed
src/test/ui/rust-2021/future-prelude-collision-imported.rs
src/test/ui/rust-2021/future-prelude-collision-imported.stderr
src/test/ui/rust-2021/future-prelude-collision-macros.fixed [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-macros.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-macros.stderr [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-shadow.stderr
src/test/ui/rust-2021/future-prelude-collision-turbofish.fixed [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-turbofish.rs [new file with mode: 0644]
src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr [new file with mode: 0644]
src/test/ui/rust-2021/reserved-prefixes.rs
src/test/ui/self/arbitrary-self-types-not-object-safe.stderr [deleted file]
src/test/ui/simd/simd-array-trait.rs
src/test/ui/simd/simd-array-trait.stderr
src/test/ui/specialization/issue-51892.rs
src/test/ui/specialization/issue-51892.stderr
src/test/ui/suggestions/if-let-typo.rs
src/test/ui/suggestions/if-let-typo.stderr
src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr
src/test/ui/suggestions/suggest-ref-macro.stderr
src/test/ui/symbol-names/basic.stderr [deleted file]
src/test/ui/symbol-names/const-generics-demangling.rs
src/test/ui/symbol-names/const-generics-demangling.stderr
src/test/ui/symbol-names/const-generics-str-demangling.rs [new file with mode: 0644]
src/test/ui/symbol-names/const-generics-str-demangling.stderr [new file with mode: 0644]
src/test/ui/symbol-names/const-generics-structural-demangling.rs [new file with mode: 0644]
src/test/ui/symbol-names/const-generics-structural-demangling.stderr [new file with mode: 0644]
src/test/ui/symbol-names/impl1.rs
src/test/ui/symbol-names/impl1.v0.stderr
src/test/ui/traits/cycle-cache-err-60010.rs
src/test/ui/traits/cycle-cache-err-60010.stderr
src/test/ui/traits/inductive-overflow/lifetime.rs
src/test/ui/traits/inductive-overflow/lifetime.stderr
src/test/ui/traits/inductive-overflow/simultaneous.stderr
src/test/ui/traits/issue-85735.stderr
src/test/ui/traits/vtable/vtable-non-object-safe.rs [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-non-object-safe.stderr [new file with mode: 0644]
src/test/ui/traits/vtable/vtable-vacant.rs
src/test/ui/traits/vtable/vtable-vacant.stderr
src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr
src/test/ui/type-alias-impl-trait/argument-types.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/argument-types.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/assoc-type-const.rs
src/test/ui/type-alias-impl-trait/assoc-type-const.stderr [deleted file]
src/test/ui/type-alias-impl-trait/auto-trait-leakage.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/field-types.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/field-types.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_nondefining_use.rs
src/test/ui/type-alias-impl-trait/generic_nondefining_use.stderr
src/test/ui/type-alias-impl-trait/generic_underconstrained.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/inference-cycle.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/inference-cycle.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr [deleted file]
src/test/ui/type-alias-impl-trait/nested-tait-inference.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/static-const-types.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/static-const-types.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/type_of_a_let.rs [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/type_of_a_let.stderr [new file with mode: 0644]
src/test/ui/type-alias-impl-trait/weird-return-types.rs [new file with mode: 0644]
src/test/ui/type/ascription/issue-34255-1.stderr
src/test/ui/typeck/struct-enum-wrong-args.stderr
src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr [deleted file]
src/test/ui/underscore-imports/shadow.stderr
src/test/ui/union/union-derive-clone.mirunsafeck.stderr
src/test/ui/union/union-derive-clone.thirunsafeck.stderr
src/test/ui/union/union-unsafe.mir.stderr
src/test/ui/unsized/param-mentioned-by-different-field.rs [new file with mode: 0644]
src/test/ui/unsized/param-mentioned-by-different-field.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
src/tools/clippy/clippy_lints/src/escape.rs
src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
src/tools/clippy/clippy_lints/src/large_const_arrays.rs
src/tools/clippy/clippy_lints/src/large_enum_variant.rs
src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
src/tools/clippy/clippy_lints/src/let_underscore.rs
src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
src/tools/clippy/clippy_lints/src/macro_use.rs
src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/missing_doc.rs
src/tools/clippy/clippy_lints/src/missing_inline.rs
src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
src/tools/clippy/clippy_lints/src/non_copy_const.rs
src/tools/clippy/clippy_lints/src/non_expressive_names.rs
src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
src/tools/clippy/clippy_lints/src/redundant_clone.rs
src/tools/clippy/clippy_lints/src/returns.rs
src/tools/clippy/clippy_lints/src/self_named_constructors.rs
src/tools/clippy/clippy_lints/src/types/vec_box.rs
src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
src/tools/clippy/clippy_lints/src/use_self.rs
src/tools/clippy/clippy_lints/src/utils/inspector.rs
src/tools/clippy/clippy_lints/src/vec.rs
src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs
src/tools/clippy/clippy_utils/src/ast_utils.rs
src/tools/clippy/clippy_utils/src/consts.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/clippy/clippy_utils/src/ty.rs
src/tools/clippy/tests/ui/crashes/ice-4775.rs
src/tools/clippy/tests/ui/crashes/ice-5223.rs
src/tools/clippy/tests/ui/doc/doc.rs
src/tools/clippy/tests/ui/match_same_arms.stderr
src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
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/clippy/tests/ui/modulo_one.stderr
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
src/tools/compiletest/src/runtest.rs
src/tools/miri
src/tools/rustfmt/src/closures.rs
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/syntux/session.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/tests/source/let_else.rs [new file with mode: 0644]
src/tools/rustfmt/tests/source/type.rs
src/tools/rustfmt/tests/target/let_else.rs [new file with mode: 0644]
src/tools/rustfmt/tests/target/type.rs
src/version
triagebot.toml

index e4612d8a954205fbb41d802012135bb6a0646d68..5b8d28752b4dada9e53b75e8910873dae58a2d1a 100644 (file)
@@ -765,9 +765,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
+checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed"
 dependencies = [
  "crossbeam-epoch",
  "crossbeam-utils 0.7.2",
@@ -871,9 +871,9 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.44+curl-7.77.0"
+version = "0.4.45+curl-7.78.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b6d85e9322b193f117c966e79c2d6929ec08c02f339f950044aba12e20bbaf1"
+checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb"
 dependencies = [
  "cc",
  "libc",
@@ -2297,9 +2297,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.26.1"
+version = "0.26.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee2766204889d09937d00bfbb7fec56bb2a199e2ade963cab19185d8a6104c7c"
+checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2"
 dependencies = [
  "compiler_builtins",
  "crc32fast",
@@ -2368,9 +2368,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
 
 [[package]]
 name = "openssl-src"
-version = "111.15.0+1.1.1k"
+version = "111.16.0+1.1.1l"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1a5f6ae2ac04393b217ea9f700cd04fa9bf3d93fae2872069f3d15d908af70a"
+checksum = "7ab2173f69416cf3ec12debb5823d244127d23a9b127d5a5189aa97c5fa2859f"
 dependencies = [
  "cc",
 ]
@@ -2729,9 +2729,9 @@ dependencies = [
 
 [[package]]
 name = "psm"
-version = "0.1.11"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96e0536f6528466dbbbbe6b986c34175a8d0ff25b794c4bacda22e068cd2f2c5"
+checksum = "cd136ff4382c4753fc061cb9e4712ab2af263376b95bbd5bd8cd50c020b78e69"
 dependencies = [
  "cc",
 ]
@@ -3398,9 +3398,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.18"
+version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
+checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -3556,6 +3556,7 @@ dependencies = [
  "rustc_parse",
  "rustc_session",
  "rustc_span",
+ "rustc_target",
  "tracing",
 ]
 
@@ -4146,6 +4147,7 @@ dependencies = [
 name = "rustc_privacy"
 version = "0.0.0"
 dependencies = [
+ "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
@@ -4404,6 +4406,7 @@ dependencies = [
  "rustc_hir_pretty",
  "rustc_index",
  "rustc_infer",
+ "rustc_lint",
  "rustc_macros",
  "rustc_middle",
  "rustc_session",
@@ -4812,12 +4815,12 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
 name = "stacker"
-version = "0.1.12"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21ccb4c06ec57bc82d0f610f1a2963d7648700e43a6f513e564b9c89f7991786"
+checksum = "90939d5171a4420b3ff5fbc8954d641e7377335454c259dcb80786f3f21dc9b4"
 dependencies = [
  "cc",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
  "libc",
  "psm",
  "winapi",
@@ -4967,9 +4970,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.35"
+version = "0.4.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80"
+checksum = "d6f5515d3add52e0bbdcad7b83c388bb36ba7b754dda3b5f5bc2d38640cdba5c"
 dependencies = [
  "filetime",
  "libc",
index 2e7077ed2065e845f5b6ef70529ef6f30977a0e3..2124195bcb209bef39423428dcda3208966cfff3 100644 (file)
@@ -70,7 +70,8 @@ Cargo
 - [The package definition in `cargo metadata` now includes the `"default_run"`
   field from the manifest.][cargo/9550]
 - [Added `cargo d` as an alias for `cargo doc`.][cargo/9680]
-- [Added `{lib}` as formatting option for `cargo tree` to print the "lib_name" of packages.][cargo/9663]
+- [Added `{lib}` as formatting option for `cargo tree` to print the `"lib_name"`
+  of packages.][cargo/9663]
 
 Rustdoc
 -------
@@ -116,9 +117,11 @@ Compatibility Notes
 [79965]: https://github.com/rust-lang/rust/pull/79965
 [87370]: https://github.com/rust-lang/rust/pull/87370
 [87298]: https://github.com/rust-lang/rust/pull/87298
+[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663
 [cargo/9675]: https://github.com/rust-lang/cargo/pull/9675
 [cargo/9550]: https://github.com/rust-lang/cargo/pull/9550
 [cargo/9680]: https://github.com/rust-lang/cargo/pull/9680
+[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663
 [`array::map`]: https://doc.rust-lang.org/stable/std/primitive.array.html#method.map
 [`Bound::cloned`]: https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.cloned
 [`Drain::as_str`]: https://doc.rust-lang.org/stable/std/string/struct.Drain.html#method.as_str
@@ -175,6 +178,7 @@ Compiler
 - [Improved debugger output for enums on Windows MSVC platforms.][85292]
 - [Added tier 3\* support for `bpfel-unknown-none`
    and `bpfeb-unknown-none`.][79608]
+- [`-Zmutable-noalias=yes`][82834] is enabled by default when using LLVM 12 or above.
 
 \* Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
@@ -244,6 +248,7 @@ Compatibility Notes
 [83366]: https://github.com/rust-lang/rust/pull/83366
 [83278]: https://github.com/rust-lang/rust/pull/83278
 [85292]: https://github.com/rust-lang/rust/pull/85292
+[82834]: https://github.com/rust-lang/rust/pull/82834
 [cargo/9520]: https://github.com/rust-lang/cargo/pull/9520
 [cargo/9499]: https://github.com/rust-lang/cargo/pull/9499
 [cargo/9488]: https://github.com/rust-lang/cargo/pull/9488
index c3e4945c4464cfadf866398839075ea2d82b5811..6d5f47aceeb91e9020674ce2078a9e9e18426eed 100644 (file)
@@ -15,6 +15,8 @@
 #![feature(new_uninit)]
 #![feature(maybe_uninit_slice)]
 #![feature(min_specialization)]
+#![feature(decl_macro)]
+#![feature(rustc_attrs)]
 #![cfg_attr(test, feature(test))]
 
 use rustc_data_structures::sync;
@@ -608,117 +610,113 @@ pub unsafe fn alloc_from_iter<T, I>(&self, iter: I) -> &mut [T]
     }
 }
 
-#[macro_export]
-macro_rules! arena_for_type {
+pub macro arena_for_type {
     ([][$ty:ty]) => {
         $crate::TypedArena<$ty>
-    };
+    },
     ([few $(, $attrs:ident)*][$ty:ty]) => {
         ::std::marker::PhantomData<$ty>
-    };
+    },
     ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
         $crate::arena_for_type!([$($attrs),*]$args)
-    };
+    },
 }
 
-#[macro_export]
-macro_rules! which_arena_for_type {
+pub macro which_arena_for_type {
     ([][$arena:expr]) => {
         ::std::option::Option::Some($arena)
-    };
+    },
     ([few$(, $attrs:ident)*][$arena:expr]) => {
         ::std::option::Option::None
-    };
+    },
     ([$ignore:ident$(, $attrs:ident)*]$args:tt) => {
         $crate::which_arena_for_type!([$($attrs),*]$args)
-    };
+    },
 }
 
-#[macro_export]
-macro_rules! declare_arena {
-    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
-        #[derive(Default)]
-        pub struct Arena<$tcx> {
-            pub dropless: $crate::DroplessArena,
-            drop: $crate::DropArena,
-            $($name: $crate::arena_for_type!($a[$ty]),)*
-        }
+#[rustc_macro_transparency = "semitransparent"]
+pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) {
+    #[derive(Default)]
+    pub struct Arena<$tcx> {
+        pub dropless: $crate::DroplessArena,
+        drop: $crate::DropArena,
+        $($name: $crate::arena_for_type!($a[$ty]),)*
+    }
 
-        pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
-            fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
-            fn allocate_from_iter<'a>(
-                arena: &'a Arena<'tcx>,
-                iter: impl ::std::iter::IntoIterator<Item = Self>,
-            ) -> &'a mut [Self];
+    pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
+        fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
+        fn allocate_from_iter<'a>(
+            arena: &'a Arena<'tcx>,
+            iter: impl ::std::iter::IntoIterator<Item = Self>,
+        ) -> &'a mut [Self];
+    }
+
+    impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
+        #[inline]
+        fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
+            arena.dropless.alloc(self)
+        }
+        #[inline]
+        fn allocate_from_iter<'a>(
+            arena: &'a Arena<'tcx>,
+            iter: impl ::std::iter::IntoIterator<Item = Self>,
+        ) -> &'a mut [Self] {
+            arena.dropless.alloc_from_iter(iter)
         }
 
-        impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
+    }
+    $(
+        impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
             #[inline]
-            fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
-                arena.dropless.alloc(self)
+            fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
+                if !::std::mem::needs_drop::<Self>() {
+                    return arena.dropless.alloc(self);
+                }
+                match $crate::which_arena_for_type!($a[&arena.$name]) {
+                    ::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
+                        ty_arena.alloc(self)
+                    }
+                    ::std::option::Option::None => unsafe { arena.drop.alloc(self) },
+                }
             }
+
             #[inline]
             fn allocate_from_iter<'a>(
-                arena: &'a Arena<'tcx>,
+                arena: &'a Arena<$tcx>,
                 iter: impl ::std::iter::IntoIterator<Item = Self>,
             ) -> &'a mut [Self] {
-                arena.dropless.alloc_from_iter(iter)
-            }
-
-        }
-        $(
-            impl<$tcx> ArenaAllocatable<$tcx, $ty> for $ty {
-                #[inline]
-                fn allocate_on<'a>(self, arena: &'a Arena<$tcx>) -> &'a mut Self {
-                    if !::std::mem::needs_drop::<Self>() {
-                        return arena.dropless.alloc(self);
-                    }
-                    match $crate::which_arena_for_type!($a[&arena.$name]) {
-                        ::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
-                            ty_arena.alloc(self)
-                        }
-                        ::std::option::Option::None => unsafe { arena.drop.alloc(self) },
-                    }
+                if !::std::mem::needs_drop::<Self>() {
+                    return arena.dropless.alloc_from_iter(iter);
                 }
-
-                #[inline]
-                fn allocate_from_iter<'a>(
-                    arena: &'a Arena<$tcx>,
-                    iter: impl ::std::iter::IntoIterator<Item = Self>,
-                ) -> &'a mut [Self] {
-                    if !::std::mem::needs_drop::<Self>() {
-                        return arena.dropless.alloc_from_iter(iter);
-                    }
-                    match $crate::which_arena_for_type!($a[&arena.$name]) {
-                        ::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
-                            ty_arena.alloc_from_iter(iter)
-                        }
-                        ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
+                match $crate::which_arena_for_type!($a[&arena.$name]) {
+                    ::std::option::Option::<&$crate::TypedArena<Self>>::Some(ty_arena) => {
+                        ty_arena.alloc_from_iter(iter)
                     }
+                    ::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
                 }
             }
-        )*
+        }
+    )*
 
-        impl<'tcx> Arena<'tcx> {
-            #[inline]
-            pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
-                value.allocate_on(self)
-            }
+    impl<'tcx> Arena<'tcx> {
+        #[inline]
+        pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
+            value.allocate_on(self)
+        }
 
-            #[inline]
-            pub fn alloc_slice<T: ::std::marker::Copy>(&self, value: &[T]) -> &mut [T] {
-                if value.is_empty() {
-                    return &mut [];
-                }
-                self.dropless.alloc_slice(value)
+        #[inline]
+        pub fn alloc_slice<T: ::std::marker::Copy>(&self, value: &[T]) -> &mut [T] {
+            if value.is_empty() {
+                return &mut [];
             }
+            self.dropless.alloc_slice(value)
+        }
 
-            pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
-                &'a self,
-                iter: impl ::std::iter::IntoIterator<Item = T>,
-            ) -> &'a mut [T] {
-                T::allocate_from_iter(self, iter)
-            }
+        pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
+            &'a self,
+            iter: impl ::std::iter::IntoIterator<Item = T>,
+        ) -> &'a mut [T] {
+            T::allocate_from_iter(self, iter)
         }
     }
 }
index 575a00cdd0e430022a1f1877ac47bf9497e4f10d..b92c5fa072786331b9c57d2eff79243c43fb67c2 100644 (file)
@@ -284,7 +284,7 @@ pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
 
 pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
 
-/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
+/// A modifier on a bound, e.g., `?Sized` or `~const Trait`.
 ///
 /// Negative bounds should also be handled here.
 #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
@@ -295,10 +295,10 @@ pub enum TraitBoundModifier {
     /// `?Trait`
     Maybe,
 
-    /// `?const Trait`
+    /// `~const Trait`
     MaybeConst,
 
-    /// `?const ?Trait`
+    /// `~const ?Trait`
     //
     // This parses but will be rejected during AST validation.
     MaybeConstMaybe,
@@ -332,8 +332,8 @@ pub fn span(&self) -> Span {
 pub enum ParamKindOrd {
     Lifetime,
     Type,
-    // `unordered` is only `true` if `sess.has_features().const_generics`
-    // is active. Specifically, if it's only `min_const_generics`, it will still require
+    // `unordered` is only `true` if `sess.unordered_const_ty_params()`
+    // returns true. Specifically, if it's only `min_const_generics`, it will still require
     // ordering consts after types.
     Const { unordered: bool },
     // `Infer` is not actually constructed directly from the AST, but is implicitly constructed
@@ -502,13 +502,6 @@ pub struct Crate {
     pub attrs: Vec<Attribute>,
     pub items: Vec<P<Item>>,
     pub span: Span,
-    /// The order of items in the HIR is unrelated to the order of
-    /// items in the AST. However, we generate proc macro harnesses
-    /// based on the AST order, and later refer to these harnesses
-    /// from the HIR. This field keeps track of the order in which
-    /// we generated proc macros harnesses, so that we can map
-    /// HIR proc macros items back to their harness items.
-    pub proc_macros: Vec<NodeId>,
 }
 
 /// Possible values inside of compile-time attribute lists.
@@ -565,6 +558,14 @@ pub struct Block {
     pub rules: BlockCheckMode,
     pub span: Span,
     pub tokens: Option<LazyTokenStream>,
+    /// The following *isn't* a parse error, but will cause multiple errors in following stages.
+    /// ```
+    /// let x = {
+    ///     foo: var
+    /// };
+    /// ```
+    /// #34255
+    pub could_be_bare_literal: bool,
 }
 
 /// A match pattern.
@@ -1005,13 +1006,42 @@ pub struct Local {
     pub id: NodeId,
     pub pat: P<Pat>,
     pub ty: Option<P<Ty>>,
-    /// Initializer expression to set the value, if any.
-    pub init: Option<P<Expr>>,
+    pub kind: LocalKind,
     pub span: Span,
     pub attrs: AttrVec,
     pub tokens: Option<LazyTokenStream>,
 }
 
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub enum LocalKind {
+    /// Local declaration.
+    /// Example: `let x;`
+    Decl,
+    /// Local declaration with an initializer.
+    /// Example: `let x = y;`
+    Init(P<Expr>),
+    /// Local declaration with an initializer and an `else` clause.
+    /// Example: `let Some(x) = y else { return };`
+    InitElse(P<Expr>, P<Block>),
+}
+
+impl LocalKind {
+    pub fn init(&self) -> Option<&Expr> {
+        match self {
+            Self::Decl => None,
+            Self::Init(i) | Self::InitElse(i, _) => Some(i),
+        }
+    }
+
+    pub fn init_else_opt(&self) -> Option<(&Expr, Option<&Block>)> {
+        match self {
+            Self::Decl => None,
+            Self::Init(init) => Some((init, None)),
+            Self::InitElse(init, els) => Some((init, Some(els))),
+        }
+    }
+}
+
 /// An arm of a 'match'.
 ///
 /// E.g., `0..=10 => { println!("match!") }` as in
@@ -2028,6 +2058,7 @@ pub enum InlineAsmOperand {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct InlineAsm {
     pub template: Vec<InlineAsmTemplatePiece>,
+    pub template_strs: Box<[(Symbol, Option<Symbol>, Span)]>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
     pub clobber_abi: Option<(Symbol, Span)>,
     pub options: InlineAsmOptions,
index 41121d095f3ed79bf3c12f997bf885b28e75f469..81195f7fb5cb2995ee4513aeac4cf0797158bcc1 100644 (file)
@@ -564,11 +564,11 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItem>
         I: Iterator<Item = TokenTree>,
     {
         match tokens.peek() {
-            Some(TokenTree::Token(token)) => {
-                if let Ok(lit) = Lit::from_token(token) {
-                    tokens.next();
-                    return Some(NestedMetaItem::Literal(lit));
-                }
+            Some(TokenTree::Token(token))
+                if let Ok(lit) = Lit::from_token(token) =>
+            {
+                tokens.next();
+                return Some(NestedMetaItem::Literal(lit));
             }
             Some(TokenTree::Delimited(_, token::NoDelim, inner_tokens)) => {
                 let inner_tokens = inner_tokens.clone();
index 502bd69e6a9af56eb4edb5fc51b6eeeef9ee8e61..ef3f6035085d3643e0abfb2aac36558a7c47031e 100644 (file)
 #![feature(box_patterns)]
 #![cfg_attr(bootstrap, feature(const_fn_transmute))]
 #![feature(crate_visibility_modifier)]
+#![feature(if_let_guard)]
 #![feature(iter_zip)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(min_specialization)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 #[macro_use]
index c8245831187223b7289e6bca7406caa63276eed7..2ec941cbb2466a95af61f5cb82254c7a1a0f4324 100644 (file)
@@ -571,11 +571,20 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
 }
 
 pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
-    let Local { id, pat, ty, init, span, attrs, tokens } = local.deref_mut();
+    let Local { id, pat, ty, kind, span, attrs, tokens } = local.deref_mut();
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(ty, |ty| vis.visit_ty(ty));
-    visit_opt(init, |init| vis.visit_expr(init));
+    match kind {
+        LocalKind::Decl => {}
+        LocalKind::Init(init) => {
+            vis.visit_expr(init);
+        }
+        LocalKind::InitElse(init, els) => {
+            vis.visit_expr(init);
+            vis.visit_block(els);
+        }
+    }
     vis.visit_span(span);
     visit_thin_attrs(attrs, vis);
     visit_lazy_tts(tokens, vis);
@@ -940,7 +949,7 @@ pub fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mu
 }
 
 pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
-    let Block { id, stmts, rules: _, span, tokens } = block.deref_mut();
+    let Block { id, stmts, rules: _, span, tokens, could_be_bare_literal: _ } = block.deref_mut();
     vis.visit_id(id);
     stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
     vis.visit_span(span);
@@ -1050,7 +1059,7 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
 // FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
 // or make crate visiting first class if necessary.
 pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
-    visit_clobber(krate, |Crate { attrs, items, span, proc_macros }| {
+    visit_clobber(krate, |Crate { attrs, items, span }| {
         let item_vis =
             Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
         let item = P(Item {
@@ -1066,13 +1075,11 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
 
         let len = items.len();
         if len == 0 {
-            Crate { attrs: vec![], items: vec![], span, proc_macros }
+            Crate { attrs: vec![], items: vec![], span }
         } else if len == 1 {
             let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
             match kind {
-                ItemKind::Mod(_, ModKind::Loaded(items, ..)) => {
-                    Crate { attrs, items, span, proc_macros }
-                }
+                ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span },
                 _ => panic!("visitor converted a module to not a module"),
             }
         } else {
@@ -1179,13 +1186,10 @@ fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
     for (op, _) in &mut asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. }
+            | InlineAsmOperand::Out { expr: Some(expr), .. }
             | InlineAsmOperand::InOut { expr, .. }
             | InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
-            InlineAsmOperand::Out { expr, .. } => {
-                if let Some(expr) = expr {
-                    vis.visit_expr(expr);
-                }
-            }
+            InlineAsmOperand::Out { expr: None, .. } => {}
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                 vis.visit_expr(in_expr);
                 if let Some(out_expr) = out_expr {
@@ -1374,7 +1378,17 @@ pub fn noop_flat_map_stmt<T: MutVisitor>(
 ) -> SmallVec<[Stmt; 1]> {
     vis.visit_id(&mut id);
     vis.visit_span(&mut span);
-    noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect()
+    let stmts: SmallVec<_> = noop_flat_map_stmt_kind(kind, vis)
+        .into_iter()
+        .map(|kind| Stmt { id, kind, span })
+        .collect();
+    if stmts.len() > 1 {
+        panic!(
+            "cloning statement `NodeId`s is prohibited by default, \
+             the visitor should implement custom statement visiting"
+        );
+    }
+    stmts
 }
 
 pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
index 90786520fe8025d5db38773f921d704e7fa80221..6ea3db6d3037252c5a2c371e2a6dabe50aebbf26 100644 (file)
@@ -23,3 +23,30 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
             | ast::ExprKind::TryBlock(..)
     )
 }
+
+/// If an expression ends with `}`, returns the innermost expression ending in the `}`
+pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
+    use ast::ExprKind::*;
+
+    loop {
+        match &expr.kind {
+            AddrOf(_, _, e)
+            | Assign(_, e, _)
+            | AssignOp(_, _, e)
+            | Binary(_, _, e)
+            | Box(e)
+            | Break(_, Some(e))
+            | Closure(.., e, _)
+            | Let(_, e, _)
+            | Range(_, Some(e), _)
+            | Ret(Some(e))
+            | Unary(_, e)
+            | Yield(Some(e)) => {
+                expr = e;
+            }
+            Async(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
+            | TryBlock(..) | While(..) => break Some(expr),
+            _ => break None,
+        }
+    }
+}
index a377763983a4bfb4b6f4fd5245b85cb8d84795a3..c30f711b3970793fdde4b52ec1c3adc40740aefa 100644 (file)
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum AssocCtxt {
     Trait,
     Impl,
 }
 
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum FnCtxt {
     Free,
     Foreign,
     Assoc(AssocCtxt),
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum FnKind<'a> {
     /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
     Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
@@ -242,7 +242,10 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
     }
     visitor.visit_pat(&local.pat);
     walk_list!(visitor, visit_ty, &local.ty);
-    walk_list!(visitor, visit_expr, &local.init);
+    if let Some((init, els)) = local.kind.init_else_opt() {
+        visitor.visit_expr(init);
+        walk_list!(visitor, visit_block, els);
+    }
 }
 
 pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {
@@ -714,13 +717,10 @@ fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
     for (op, _) in &asm.operands {
         match op {
             InlineAsmOperand::In { expr, .. }
+            | InlineAsmOperand::Out { expr: Some(expr), .. }
             | InlineAsmOperand::InOut { expr, .. }
             | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
-            InlineAsmOperand::Out { expr, .. } => {
-                if let Some(expr) = expr {
-                    visitor.visit_expr(expr);
-                }
-            }
+            InlineAsmOperand::Out { expr: None, .. } => {}
             InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                 visitor.visit_expr(in_expr);
                 if let Some(out_expr) = out_expr {
index d94fb48d7cb883513e8798c55cc41a800c1dd164..7165b3bcb9fc1eee77267759de7c315c8e02548f 100644 (file)
@@ -128,7 +128,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
-                (op, *op_sp)
+                (op, self.lower_span(*op_sp))
             })
             .collect();
 
@@ -384,7 +384,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             late: true,
                             expr: None,
                         },
-                        abi_span,
+                        self.lower_span(abi_span),
                     ));
                 }
             }
@@ -392,8 +392,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let operands = self.arena.alloc_from_iter(operands);
         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
-        let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
-        let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
+        let template_strs = self.arena.alloc_from_iter(
+            asm.template_strs
+                .iter()
+                .map(|(sym, snippet, span)| (*sym, *snippet, self.lower_span(*span))),
+        );
+        let line_spans =
+            self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span)));
+        let hir_asm =
+            hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
         self.arena.alloc(hir_asm)
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
new file mode 100644 (file)
index 0000000..ca804ec
--- /dev/null
@@ -0,0 +1,185 @@
+use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
+use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind};
+use rustc_hir as hir;
+use rustc_session::parse::feature_err;
+use rustc_span::symbol::Ident;
+use rustc_span::{sym, DesugaringKind};
+
+use smallvec::SmallVec;
+
+impl<'a, 'hir> LoweringContext<'a, 'hir> {
+    pub(super) fn lower_block(
+        &mut self,
+        b: &Block,
+        targeted_by_break: bool,
+    ) -> &'hir hir::Block<'hir> {
+        self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
+    }
+
+    pub(super) fn lower_block_noalloc(
+        &mut self,
+        b: &Block,
+        targeted_by_break: bool,
+    ) -> hir::Block<'hir> {
+        let (stmts, expr) = self.lower_stmts(&b.stmts);
+        let rules = self.lower_block_check_mode(&b.rules);
+        let hir_id = self.lower_node_id(b.id);
+        hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
+    }
+
+    fn lower_stmts(
+        &mut self,
+        mut ast_stmts: &[Stmt],
+    ) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) {
+        let mut stmts = SmallVec::<[hir::Stmt<'hir>; 8]>::new();
+        let mut expr = None;
+        while let [s, tail @ ..] = ast_stmts {
+            match s.kind {
+                StmtKind::Local(ref local) => {
+                    let hir_id = self.lower_node_id(s.id);
+                    match &local.kind {
+                        LocalKind::InitElse(init, els) => {
+                            let (s, e) = self.lower_let_else(hir_id, local, init, els, tail);
+                            stmts.push(s);
+                            expr = Some(e);
+                            // remaining statements are in let-else expression
+                            break;
+                        }
+                        _ => {
+                            let local = self.lower_local(local);
+                            self.alias_attrs(hir_id, local.hir_id);
+                            let kind = hir::StmtKind::Local(local);
+                            let span = self.lower_span(s.span);
+                            stmts.push(hir::Stmt { hir_id, kind, span });
+                        }
+                    }
+                }
+                StmtKind::Item(ref it) => {
+                    stmts.extend(self.lower_item_id(it).into_iter().enumerate().map(
+                        |(i, item_id)| {
+                            let hir_id = match i {
+                                0 => self.lower_node_id(s.id),
+                                _ => self.next_id(),
+                            };
+                            let kind = hir::StmtKind::Item(item_id);
+                            let span = self.lower_span(s.span);
+                            hir::Stmt { hir_id, kind, span }
+                        },
+                    ));
+                }
+                StmtKind::Expr(ref e) => {
+                    let e = self.lower_expr(e);
+                    if tail.is_empty() {
+                        expr = Some(e);
+                    } else {
+                        let hir_id = self.lower_node_id(s.id);
+                        self.alias_attrs(hir_id, e.hir_id);
+                        let kind = hir::StmtKind::Expr(e);
+                        let span = self.lower_span(s.span);
+                        stmts.push(hir::Stmt { hir_id, kind, span });
+                    }
+                }
+                StmtKind::Semi(ref e) => {
+                    let e = self.lower_expr(e);
+                    let hir_id = self.lower_node_id(s.id);
+                    self.alias_attrs(hir_id, e.hir_id);
+                    let kind = hir::StmtKind::Semi(e);
+                    let span = self.lower_span(s.span);
+                    stmts.push(hir::Stmt { hir_id, kind, span });
+                }
+                StmtKind::Empty => {}
+                StmtKind::MacCall(..) => panic!("shouldn't exist here"),
+            }
+            ast_stmts = &ast_stmts[1..];
+        }
+        (self.arena.alloc_from_iter(stmts), expr)
+    }
+
+    fn lower_local(&mut self, l: &Local) -> &'hir hir::Local<'hir> {
+        let ty = l
+            .ty
+            .as_ref()
+            .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
+        let init = l.kind.init().map(|init| self.lower_expr(init));
+        let hir_id = self.lower_node_id(l.id);
+        let pat = self.lower_pat(&l.pat);
+        let span = self.lower_span(l.span);
+        let source = hir::LocalSource::Normal;
+        self.lower_attrs(hir_id, &l.attrs);
+        self.arena.alloc(hir::Local { hir_id, ty, pat, init, span, source })
+    }
+
+    fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
+        match *b {
+            BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
+            BlockCheckMode::Unsafe(u) => {
+                hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
+            }
+        }
+    }
+
+    fn lower_let_else(
+        &mut self,
+        stmt_hir_id: hir::HirId,
+        local: &Local,
+        init: &Expr,
+        els: &Block,
+        tail: &[Stmt],
+    ) -> (hir::Stmt<'hir>, &'hir hir::Expr<'hir>) {
+        let ty = local
+            .ty
+            .as_ref()
+            .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
+        let span = self.lower_span(local.span);
+        let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None);
+        let init = Some(self.lower_expr(init));
+        let val = Ident::with_dummy_span(sym::val);
+        let (pat, val_id) =
+            self.pat_ident_binding_mode(span, val, hir::BindingAnnotation::Unannotated);
+        let local_hir_id = self.lower_node_id(local.id);
+        self.lower_attrs(local_hir_id, &local.attrs);
+        // first statement which basically exists for the type annotation
+        let stmt = {
+            let local = self.arena.alloc(hir::Local {
+                hir_id: local_hir_id,
+                ty,
+                pat,
+                init,
+                span,
+                source: hir::LocalSource::Normal,
+            });
+            let kind = hir::StmtKind::Local(local);
+            hir::Stmt { hir_id: stmt_hir_id, kind, span }
+        };
+        let let_expr = {
+            let scrutinee = self.expr_ident(span, val, val_id);
+            let let_kind = hir::ExprKind::Let(self.lower_pat(&local.pat), scrutinee, span);
+            self.arena.alloc(self.expr(span, let_kind, AttrVec::new()))
+        };
+        let then_expr = {
+            let (stmts, expr) = self.lower_stmts(tail);
+            let block = self.block_all(span, stmts, expr);
+            self.arena.alloc(self.expr_block(block, AttrVec::new()))
+        };
+        let else_expr = {
+            let block = self.lower_block(els, false);
+            self.arena.alloc(self.expr_block(block, AttrVec::new()))
+        };
+        self.alias_attrs(else_expr.hir_id, local_hir_id);
+        let if_expr = self.arena.alloc(hir::Expr {
+            hir_id: self.next_id(),
+            span,
+            kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)),
+        });
+        if !self.sess.features_untracked().let_else {
+            feature_err(
+                &self.sess.parse_sess,
+                sym::let_else,
+                local.span,
+                "`let...else` statements are unstable",
+            )
+            .emit();
+        }
+        (stmt, if_expr)
+    }
+}
index bf7589e84adc42c8049e7d50341b6a684e53e4d1..16cd7a0bcdd394af214d0a0235fab976fb3c3636 100644 (file)
@@ -58,7 +58,12 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                         None,
                     ));
                     let args = self.lower_exprs(args);
-                    hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
+                    hir::ExprKind::MethodCall(
+                        hir_seg,
+                        self.lower_span(seg.ident.span),
+                        args,
+                        self.lower_span(span),
+                    )
                 }
                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
                     let binop = self.lower_binop(binop);
@@ -71,7 +76,9 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::Unary(op, ohs)
                 }
-                ExprKind::Lit(ref l) => hir::ExprKind::Lit(respan(l.span, l.kind.clone())),
+                ExprKind::Lit(ref l) => {
+                    hir::ExprKind::Lit(respan(self.lower_span(l.span), l.kind.clone()))
+                }
                 ExprKind::Cast(ref expr, ref ty) => {
                     let expr = self.lower_expr(expr);
                     let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
@@ -86,9 +93,11 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::AddrOf(k, m, ohs)
                 }
-                ExprKind::Let(ref pat, ref scrutinee, span) => {
-                    hir::ExprKind::Let(self.lower_pat(pat), self.lower_expr(scrutinee), span)
-                }
+                ExprKind::Let(ref pat, ref scrutinee, span) => hir::ExprKind::Let(
+                    self.lower_pat(pat),
+                    self.lower_expr(scrutinee),
+                    self.lower_span(span),
+                ),
                 ExprKind::If(ref cond, ref then, ref else_opt) => {
                     self.lower_expr_if(cond, then, else_opt.as_deref())
                 }
@@ -99,7 +108,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                 ExprKind::Loop(ref body, opt_label) => self.with_loop_scope(e.id, |this| {
                     hir::ExprKind::Loop(
                         this.lower_block(body, false),
-                        opt_label,
+                        this.lower_label(opt_label),
                         hir::LoopSource::Loop,
                         DUMMY_SP,
                     )
@@ -147,6 +156,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     }
                 }
                 ExprKind::Block(ref blk, opt_label) => {
+                    let opt_label = self.lower_label(opt_label);
                     hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label)
                 }
                 ExprKind::Assign(ref el, ref er, span) => {
@@ -157,7 +167,9 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     self.lower_expr(el),
                     self.lower_expr(er),
                 ),
-                ExprKind::Field(ref el, ident) => hir::ExprKind::Field(self.lower_expr(el), ident),
+                ExprKind::Field(ref el, ident) => {
+                    hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(ident))
+                }
                 ExprKind::Index(ref el, ref er) => {
                     hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er))
                 }
@@ -234,7 +246,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                     let mut ex = self.lower_expr_mut(ex);
                     // Include parens in span, but only if it is a super-span.
                     if e.span.contains(ex.span) {
-                        ex.span = e.span;
+                        ex.span = self.lower_span(e.span);
                     }
                     // Merge attributes into the inner expression.
                     if !e.attrs.is_empty() {
@@ -262,7 +274,7 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
 
             let hir_id = self.lower_node_id(e.id);
             self.lower_attrs(hir_id, &e.attrs);
-            hir::Expr { hir_id, kind, span: e.span }
+            hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
         })
     }
 
@@ -296,7 +308,7 @@ fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
                 BinOpKind::Ge => hir::BinOpKind::Ge,
                 BinOpKind::Gt => hir::BinOpKind::Gt,
             },
-            span: b.span,
+            span: self.lower_span(b.span),
         }
     }
 
@@ -478,7 +490,13 @@ fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
         });
         let hir_id = self.next_id();
         self.lower_attrs(hir_id, &arm.attrs);
-        hir::Arm { hir_id, pat, guard, body: self.lower_expr(&arm.body), span: arm.span }
+        hir::Arm {
+            hir_id,
+            pat,
+            guard,
+            body: self.lower_expr(&arm.body),
+            span: self.lower_span(arm.span),
+        }
     }
 
     /// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
@@ -501,12 +519,16 @@ pub(super) fn make_async_expr(
     ) -> hir::ExprKind<'hir> {
         let output = match ret_ty {
             Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())),
-            None => hir::FnRetTy::DefaultReturn(span),
+            None => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
         };
 
         // Resume argument type. We let the compiler infer this to simplify the lowering. It is
         // fully constrained by `future::from_generator`.
-        let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span };
+        let input_ty = hir::Ty {
+            hir_id: self.next_id(),
+            kind: hir::TyKind::Infer,
+            span: self.lower_span(span),
+        };
 
         // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
         let decl = self.arena.alloc(hir::FnDecl {
@@ -522,7 +544,12 @@ pub(super) fn make_async_expr(
             Ident::with_dummy_span(sym::_task_context),
             hir::BindingAnnotation::Mutable,
         );
-        let param = hir::Param { hir_id: self.next_id(), pat, ty_span: span, span };
+        let param = hir::Param {
+            hir_id: self.next_id(),
+            pat,
+            ty_span: self.lower_span(span),
+            span: self.lower_span(span),
+        };
         let params = arena_vec![self; param];
 
         let body_id = self.lower_body(move |this| {
@@ -540,11 +567,14 @@ pub(super) fn make_async_expr(
             capture_clause,
             decl,
             body_id,
-            span,
+            self.lower_span(span),
             Some(hir::Movability::Static),
         );
-        let generator =
-            hir::Expr { hir_id: self.lower_node_id(closure_node_id), kind: generator_kind, span };
+        let generator = hir::Expr {
+            hir_id: self.lower_node_id(closure_node_id),
+            kind: generator_kind,
+            span: self.lower_span(span),
+        };
 
         // `future::from_generator`:
         let unstable_span =
@@ -681,8 +711,11 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
 
             if let Some(task_context_hid) = self.task_context {
                 let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
-                let assign =
-                    self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new());
+                let assign = self.expr(
+                    span,
+                    hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span)),
+                    AttrVec::new(),
+                );
                 self.stmt_expr(span, assign)
             } else {
                 // Use of `await` outside of an async context. Return `yield_expr` so that we can
@@ -696,8 +729,13 @@ fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'
         // loop { .. }
         let loop_expr = self.arena.alloc(hir::Expr {
             hir_id: loop_hir_id,
-            kind: hir::ExprKind::Loop(loop_block, None, hir::LoopSource::Loop, span),
-            span,
+            kind: hir::ExprKind::Loop(
+                loop_block,
+                None,
+                hir::LoopSource::Loop,
+                self.lower_span(span),
+            ),
+            span: self.lower_span(span),
         });
 
         // mut pinned => loop { ... }
@@ -735,7 +773,13 @@ fn lower_expr_closure(
         // Lower outside new scope to preserve `is_in_loop_condition`.
         let fn_decl = self.lower_fn_decl(decl, None, false, None);
 
-        hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
+        hir::ExprKind::Closure(
+            capture_clause,
+            fn_decl,
+            body_id,
+            self.lower_span(fn_decl_span),
+            generator_option,
+        )
     }
 
     fn generator_movability_for_fn(
@@ -821,7 +865,13 @@ fn lower_expr_async_closure(
         // closure argument types.
         let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
 
-        hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
+        hir::ExprKind::Closure(
+            capture_clause,
+            fn_decl,
+            body_id,
+            self.lower_span(fn_decl_span),
+            None,
+        )
     }
 
     /// Destructure the LHS of complex assignments.
@@ -853,7 +903,11 @@ fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
             }
         }
         if is_ordinary(self, lhs) {
-            return hir::ExprKind::Assign(self.lower_expr(lhs), self.lower_expr(rhs), eq_sign_span);
+            return hir::ExprKind::Assign(
+                self.lower_expr(lhs),
+                self.lower_expr(rhs),
+                self.lower_span(eq_sign_span),
+            );
         }
         if !self.sess.features_untracked().destructuring_assignment {
             feature_err(
@@ -878,7 +932,7 @@ fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
             whole_span,
             Some(rhs),
             pat,
-            hir::LocalSource::AssignDesugar(eq_sign_span),
+            hir::LocalSource::AssignDesugar(self.lower_span(eq_sign_span)),
         );
 
         // `a = lhs1; b = lhs2;`.
@@ -978,10 +1032,10 @@ fn destructure_assign_mut(
                     let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments);
                     hir::PatField {
                         hir_id: self.next_id(),
-                        ident: f.ident,
+                        ident: self.lower_ident(f.ident),
                         pat,
                         is_shorthand: f.is_shorthand,
-                        span: f.span,
+                        span: self.lower_span(f.span),
                     }
                 }));
                 let qpath = self.lower_qpath(
@@ -1033,10 +1087,11 @@ fn destructure_assign_mut(
             _ => {}
         }
         // Treat all other cases as normal lvalue.
-        let ident = Ident::new(sym::lhs, lhs.span);
+        let ident = Ident::new(sym::lhs, self.lower_span(lhs.span));
         let (pat, binding) = self.pat_ident_mut(lhs.span, ident);
         let ident = self.expr_ident(lhs.span, ident, binding);
-        let assign = hir::ExprKind::Assign(self.lower_expr(lhs), ident, eq_sign_span);
+        let assign =
+            hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
         let expr = self.expr(lhs.span, assign, ThinVec::new());
         assignments.push(self.stmt_expr(lhs.span, expr));
         pat
@@ -1076,7 +1131,7 @@ fn destructure_sequence(
     fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
         let e1 = self.lower_expr_mut(e1);
         let e2 = self.lower_expr_mut(e2);
-        let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, span);
+        let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span));
         let fn_expr =
             self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
@@ -1104,12 +1159,21 @@ fn lower_expr_range(
         let fields = self.arena.alloc_from_iter(
             e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))).map(|(s, e)| {
                 let expr = self.lower_expr(&e);
-                let ident = Ident::new(Symbol::intern(s), e.span);
+                let ident = Ident::new(Symbol::intern(s), self.lower_span(e.span));
                 self.expr_field(ident, expr, e.span)
             }),
         );
 
-        hir::ExprKind::Struct(self.arena.alloc(hir::QPath::LangItem(lang_item, span)), fields, None)
+        hir::ExprKind::Struct(
+            self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))),
+            fields,
+            None,
+        )
+    }
+
+    fn lower_label(&self, opt_label: Option<Label>) -> Option<Label> {
+        let label = opt_label?;
+        Some(Label { ident: self.lower_ident(label.ident) })
     }
 
     fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
@@ -1122,13 +1186,12 @@ fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hi
                 }
             }
             None => self
-                .loop_scopes
-                .last()
-                .cloned()
+                .loop_scope
                 .map(|id| Ok(self.lower_node_id(id)))
                 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)),
         };
-        hir::Destination { label: destination.map(|(_, label)| label), target_id }
+        let label = self.lower_label(destination.map(|(_, label)| label));
+        hir::Destination { label, target_id }
     }
 
     fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
@@ -1143,18 +1206,9 @@ fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hi
     }
 
     fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
-        let len = self.catch_scopes.len();
-        self.catch_scopes.push(catch_id);
-
+        let old_scope = self.catch_scope.replace(catch_id);
         let result = f(self);
-        assert_eq!(
-            len + 1,
-            self.catch_scopes.len(),
-            "catch scopes should be added and removed in stack order"
-        );
-
-        self.catch_scopes.pop().unwrap();
-
+        self.catch_scope = old_scope;
         result
     }
 
@@ -1163,17 +1217,9 @@ fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
-        let len = self.loop_scopes.len();
-        self.loop_scopes.push(loop_id);
-
+        let old_scope = self.loop_scope.replace(loop_id);
         let result = f(self);
-        assert_eq!(
-            len + 1,
-            self.loop_scopes.len(),
-            "loop scopes should be added and removed in stack order"
-        );
-
-        self.loop_scopes.pop().unwrap();
+        self.loop_scope = old_scope;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
@@ -1201,7 +1247,7 @@ fn lower_expr_llvm_asm(&mut self, asm: &LlvmInlineAsm) -> hir::ExprKind<'hir> {
                     constraint: out.constraint,
                     is_rw: out.is_rw,
                     is_indirect: out.is_indirect,
-                    span: out.expr.span,
+                    span: self.lower_span(out.expr.span),
                 })
                 .collect(),
             asm: asm.asm,
@@ -1226,9 +1272,9 @@ fn lower_expr_llvm_asm(&mut self, asm: &LlvmInlineAsm) -> hir::ExprKind<'hir> {
     fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> {
         hir::ExprField {
             hir_id: self.next_id(),
-            ident: f.ident,
+            ident: self.lower_ident(f.ident),
             expr: self.lower_expr(&f.expr),
-            span: f.span,
+            span: self.lower_span(f.span),
             is_shorthand: f.is_shorthand,
         }
     }
@@ -1289,7 +1335,7 @@ fn lower_expr_for(
             orig_head_span,
             None,
         );
-        head.span = desugared_span;
+        head.span = self.lower_span(desugared_span);
 
         let iter = Ident::with_dummy_span(sym::iter);
 
@@ -1308,7 +1354,7 @@ fn lower_expr_for(
             let next_expr = self.expr_ident(pat.span, next_ident, next_pat_hid);
             let assign = self.arena.alloc(self.expr(
                 pat.span,
-                hir::ExprKind::Assign(next_expr, val_expr, pat.span),
+                hir::ExprKind::Assign(next_expr, val_expr, self.lower_span(pat.span)),
                 ThinVec::new(),
             ));
             let some_pat = self.pat_some(pat.span, val_pat);
@@ -1376,12 +1422,15 @@ fn lower_expr_for(
         // `[opt_ident]: loop { ... }`
         let kind = hir::ExprKind::Loop(
             loop_block,
-            opt_label,
+            self.lower_label(opt_label),
             hir::LoopSource::ForLoop,
-            e.span.with_hi(orig_head_span.hi()),
+            self.lower_span(e.span.with_hi(orig_head_span.hi())),
         );
-        let loop_expr =
-            self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: e.span });
+        let loop_expr = self.arena.alloc(hir::Expr {
+            hir_id: self.lower_node_id(e.id),
+            kind,
+            span: self.lower_span(e.span),
+        });
 
         // `mut iter => { ... }`
         let iter_arm = self.arm(iter_pat, loop_expr);
@@ -1460,8 +1509,8 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
         let attr = {
             // `allow(unreachable_code)`
             let allow = {
-                let allow_ident = Ident::new(sym::allow, span);
-                let uc_ident = Ident::new(sym::unreachable_code, span);
+                let allow_ident = Ident::new(sym::allow, self.lower_span(span));
+                let uc_ident = Ident::new(sym::unreachable_code, self.lower_span(span));
                 let uc_nested = attr::mk_nested_word_item(uc_ident);
                 attr::mk_list_item(allow_ident, vec![uc_nested])
             };
@@ -1497,8 +1546,7 @@ fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>
                 unstable_span,
             );
             let thin_attrs = ThinVec::from(attrs);
-            let catch_scope = self.catch_scopes.last().copied();
-            let ret_expr = if let Some(catch_node) = catch_scope {
+            let ret_expr = if let Some(catch_node) = self.catch_scope {
                 let target_id = Ok(self.lower_node_id(catch_node));
                 self.arena.alloc(self.expr(
                     try_span,
@@ -1630,7 +1678,11 @@ fn expr_lang_item_path(
         lang_item: hir::LangItem,
         attrs: AttrVec,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Path(hir::QPath::LangItem(lang_item, span)), attrs)
+        self.expr(
+            span,
+            hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))),
+            attrs,
+        )
     }
 
     pub(super) fn expr_ident(
@@ -1661,7 +1713,7 @@ fn expr_ident_with_attrs(
         let expr_path = hir::ExprKind::Path(hir::QPath::Resolved(
             None,
             self.arena.alloc(hir::Path {
-                span,
+                span: self.lower_span(span),
                 res: Res::Local(binding),
                 segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
             }),
@@ -1681,7 +1733,7 @@ fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> {
                     expr: Some(expr),
                     hir_id,
                     rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated),
-                    span,
+                    span: self.lower_span(span),
                     targeted_by_break: false,
                 }),
                 None,
@@ -1712,7 +1764,7 @@ pub(super) fn expr(
     ) -> hir::Expr<'hir> {
         let hir_id = self.next_id();
         self.lower_attrs(hir_id, &attrs);
-        hir::Expr { hir_id, kind, span }
+        hir::Expr { hir_id, kind, span: self.lower_span(span) }
     }
 
     fn expr_field(
@@ -1721,10 +1773,22 @@ fn expr_field(
         expr: &'hir hir::Expr<'hir>,
         span: Span,
     ) -> hir::ExprField<'hir> {
-        hir::ExprField { hir_id: self.next_id(), ident, span, expr, is_shorthand: false }
+        hir::ExprField {
+            hir_id: self.next_id(),
+            ident,
+            span: self.lower_span(span),
+            expr,
+            is_shorthand: false,
+        }
     }
 
     fn arm(&mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>) -> hir::Arm<'hir> {
-        hir::Arm { hir_id: self.next_id(), pat, guard: None, span: expr.span, body: expr }
+        hir::Arm {
+            hir_id: self.next_id(),
+            pat,
+            guard: None,
+            span: self.lower_span(expr.span),
+            body: expr,
+        }
     }
 }
index 3acf69ec2b7d0139873485048b751e2ce406e655..e0d4095d76907362e7b3ecb02dabc85f81b2438b 100644 (file)
@@ -26,44 +26,43 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
 }
 
 impl ItemLowerer<'_, '_, '_> {
-    fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
+    fn with_trait_impl_ref<T>(
+        &mut self,
+        impl_ref: &Option<TraitRef>,
+        f: impl FnOnce(&mut Self) -> T,
+    ) -> T {
         let old = self.lctx.is_in_trait_impl;
         self.lctx.is_in_trait_impl = impl_ref.is_some();
-        f(self);
+        let ret = f(self);
         self.lctx.is_in_trait_impl = old;
+        ret
     }
 }
 
 impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     fn visit_item(&mut self, item: &'a Item) {
-        let mut item_hir_id = None;
-        self.lctx.with_hir_id_owner(item.id, |lctx| {
+        let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
             lctx.without_in_scope_lifetime_defs(|lctx| {
-                if let Some(hir_item) = lctx.lower_item(item) {
-                    let id = lctx.insert_item(hir_item);
-                    item_hir_id = Some(id);
-                }
+                let hir_item = lctx.lower_item(item);
+                lctx.insert_item(hir_item)
             })
         });
 
-        if let Some(hir_id) = item_hir_id {
-            self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
-                let this = &mut ItemLowerer { lctx: this };
-                match item.kind {
-                    ItemKind::Mod(..) => {
-                        let def_id = this.lctx.lower_node_id(item.id).expect_owner();
-                        let old_current_module =
-                            mem::replace(&mut this.lctx.current_module, def_id);
-                        visit::walk_item(this, item);
-                        this.lctx.current_module = old_current_module;
-                    }
-                    ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
-                        this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
-                    }
-                    _ => visit::walk_item(this, item),
+        self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
+            let this = &mut ItemLowerer { lctx: this };
+            match item.kind {
+                ItemKind::Mod(..) => {
+                    let def_id = this.lctx.lower_node_id(item.id).expect_owner();
+                    let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
+                    visit::walk_item(this, item);
+                    this.lctx.current_module = old_current_module;
                 }
-            });
-        }
+                ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
+                    this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
+                }
+                _ => visit::walk_item(this, item),
+            }
+        });
     }
 
     fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
@@ -113,7 +112,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn with_parent_item_lifetime_defs<T>(
         &mut self,
         parent_hir_id: hir::ItemId,
-        f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
+        f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
 
@@ -137,10 +136,7 @@ fn with_parent_item_lifetime_defs<T>(
     // Clears (and restores) the `in_scope_lifetimes` field. Used when
     // visiting nested items, which never inherit in-scope lifetimes
     // from their surrounding environment.
-    fn without_in_scope_lifetime_defs<T>(
-        &mut self,
-        f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
-    ) -> T {
+    fn without_in_scope_lifetime_defs<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]);
 
         // this vector is only used when walking over impl headers,
@@ -158,7 +154,7 @@ fn without_in_scope_lifetime_defs<T>(
 
     pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
         hir::Mod {
-            inner,
+            inner: self.lower_span(inner),
             item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))),
         }
     }
@@ -170,7 +166,6 @@ pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'
                 self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
                 vec
             }
-            ItemKind::MacroDef(..) => SmallVec::new(),
             ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
                 smallvec![i.id]
             }
@@ -209,35 +204,19 @@ fn lower_item_id_use_tree(
         }
     }
 
-    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
+    pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
         let mut ident = i.ident;
         let mut vis = self.lower_visibility(&i.vis, None);
-
-        if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind {
-            if !macro_rules || self.sess.contains_name(&i.attrs, sym::macro_export) {
-                let hir_id = self.lower_node_id(i.id);
-                self.lower_attrs(hir_id, &i.attrs);
-                let body = P(self.lower_mac_args(body));
-                self.insert_macro_def(hir::MacroDef {
-                    ident,
-                    vis,
-                    def_id: hir_id.expect_owner(),
-                    span: i.span,
-                    ast: MacroDef { body, macro_rules },
-                });
-            } else {
-                for a in i.attrs.iter() {
-                    let a = self.lower_attr(a);
-                    self.non_exported_macro_attrs.push(a);
-                }
-            }
-            return None;
-        }
-
         let hir_id = self.lower_node_id(i.id);
         let attrs = self.lower_attrs(hir_id, &i.attrs);
         let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
-        Some(hir::Item { def_id: hir_id.expect_owner(), ident, kind, vis, span: i.span })
+        hir::Item {
+            def_id: hir_id.expect_owner(),
+            ident: self.lower_ident(ident),
+            kind,
+            vis,
+            span: self.lower_span(i.span),
+        }
     }
 
     fn lower_item_kind(
@@ -300,8 +279,8 @@ fn lower_item_kind(
                     );
                     let sig = hir::FnSig {
                         decl,
-                        header: this.lower_fn_header(header, fn_sig_span, id),
-                        span: fn_sig_span,
+                        header: this.lower_fn_header(header),
+                        span: this.lower_span(fn_sig_span),
                     };
                     hir::ItemKind::Fn(sig, generics, body_id)
                 })
@@ -312,17 +291,12 @@ fn lower_item_kind(
                 }
                 ModKind::Unloaded => panic!("`mod` items should have been loaded by now"),
             },
-            ItemKind::ForeignMod(ref fm) => {
-                if fm.abi.is_none() {
-                    self.maybe_lint_missing_abi(span, id, abi::Abi::C { unwind: false });
-                }
-                hir::ItemKind::ForeignMod {
-                    abi: fm.abi.map_or(abi::Abi::C { unwind: false }, |abi| self.lower_abi(abi)),
-                    items: self
-                        .arena
-                        .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
-                }
-            }
+            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
+                abi: fm.abi.map_or(abi::Abi::FALLBACK, |abi| self.lower_abi(abi)),
+                items: self
+                    .arena
+                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+            },
             ItemKind::GlobalAsm(ref asm) => {
                 hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
             }
@@ -404,15 +378,6 @@ fn lower_item_kind(
                             this.lower_trait_ref(trait_ref, ImplTraitContext::disallowed())
                         });
 
-                        if let Some(ref trait_ref) = trait_ref {
-                            if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res {
-                                this.trait_impls
-                                    .entry(def_id)
-                                    .or_default()
-                                    .push(lowered_trait_def_id);
-                            }
-                        }
-
                         let lowered_ty = this.lower_ty(ty, ImplTraitContext::disallowed());
 
                         (trait_ref, lowered_ty)
@@ -430,6 +395,10 @@ fn lower_item_kind(
                 // to not cause an assertion failure inside the `lower_defaultness` function.
                 let has_val = true;
                 let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
+                let polarity = match polarity {
+                    ImplPolarity::Positive => ImplPolarity::Positive,
+                    ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
+                };
                 hir::ItemKind::Impl(hir::Impl {
                     unsafety: self.lower_unsafety(unsafety),
                     polarity,
@@ -465,7 +434,12 @@ fn lower_item_kind(
                 self.lower_generics(generics, ImplTraitContext::disallowed()),
                 self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
             ),
-            ItemKind::MacroDef(..) | ItemKind::MacCall(..) => {
+            ItemKind::MacroDef(MacroDef { ref body, macro_rules }) => {
+                let body = P(self.lower_mac_args(body));
+
+                hir::ItemKind::Macro(ast::MacroDef { body, macro_rules })
+            }
+            ItemKind::MacCall(..) => {
                 panic!("`TyMac` should have been expanded by now")
             }
         }
@@ -543,10 +517,10 @@ fn lower_use_tree(
 
                         this.insert_item(hir::Item {
                             def_id: new_id.expect_owner(),
-                            ident,
+                            ident: this.lower_ident(ident),
                             kind,
                             vis,
-                            span,
+                            span: this.lower_span(span),
                         });
                     });
                 }
@@ -617,10 +591,10 @@ fn lower_use_tree(
 
                         this.insert_item(hir::Item {
                             def_id: new_hir_id.expect_owner(),
-                            ident,
+                            ident: this.lower_ident(ident),
                             kind,
                             vis,
-                            span: use_tree.span,
+                            span: this.lower_span(use_tree.span),
                         });
                     });
                 }
@@ -639,7 +613,10 @@ fn lower_use_tree(
                     hir::VisibilityKind::Public
                     | hir::VisibilityKind::Crate(_)
                     | hir::VisibilityKind::Inherited => {
-                        *vis = respan(prefix.span.shrink_to_lo(), hir::VisibilityKind::Inherited);
+                        *vis = respan(
+                            self.lower_span(prefix.span.shrink_to_lo()),
+                            hir::VisibilityKind::Inherited,
+                        );
                     }
                     hir::VisibilityKind::Restricted { .. } => {
                         // Do nothing here, as described in the comment on the match.
@@ -682,7 +659,7 @@ fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir>
                 }
             }
         };
-        respan(vis.span, vis_kind)
+        respan(self.lower_span(vis.span), vis_kind)
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
@@ -691,7 +668,7 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
         self.lower_attrs(hir_id, &i.attrs);
         hir::ForeignItem {
             def_id,
-            ident: i.ident,
+            ident: self.lower_ident(i.ident),
             kind: match i.kind {
                 ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
                     let fdec = &sig.decl;
@@ -718,15 +695,15 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
                 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
             },
             vis: self.lower_visibility(&i.vis, None),
-            span: i.span,
+            span: self.lower_span(i.span),
         }
     }
 
     fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
         hir::ForeignItemRef {
             id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() },
-            ident: i.ident,
-            span: i.span,
+            ident: self.lower_ident(i.ident),
+            span: self.lower_span(i.span),
             vis: self.lower_visibility(&i.vis, Some(i.id)),
         }
     }
@@ -738,8 +715,8 @@ fn lower_variant(&mut self, v: &Variant) -> hir::Variant<'hir> {
             id,
             data: self.lower_variant_data(id, &v.data),
             disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
-            ident: v.ident,
-            span: v.span,
+            ident: self.lower_ident(v.ident),
+            span: self.lower_span(v.span),
         }
     }
 
@@ -791,12 +768,12 @@ pub(super) fn lower_field_def(
         let hir_id = self.lower_node_id(f.id);
         self.lower_attrs(hir_id, &f.attrs);
         hir::FieldDef {
-            span: f.span,
+            span: self.lower_span(f.span),
             hir_id,
             ident: match f.ident {
-                Some(ident) => ident,
+                Some(ident) => self.lower_ident(ident),
                 // FIXME(jseyfried): positional field hygiene.
-                None => Ident::new(sym::integer(index), f.span),
+                None => Ident::new(sym::integer(index), self.lower_span(f.span)),
             },
             vis: self.lower_visibility(&f.vis, None),
             ty,
@@ -816,7 +793,7 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
             AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, None)) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
-                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
+                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
             AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => {
@@ -829,7 +806,6 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
                     trait_item_def_id,
                     false,
                     asyncness.opt_return_id(),
-                    i.id,
                 );
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
@@ -847,7 +823,13 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
         };
 
         self.lower_attrs(hir_id, &i.attrs);
-        hir::TraitItem { def_id: trait_item_def_id, ident: i.ident, generics, kind, span: i.span }
+        hir::TraitItem {
+            def_id: trait_item_def_id,
+            ident: self.lower_ident(i.ident),
+            generics,
+            kind,
+            span: self.lower_span(i.span),
+        }
     }
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
@@ -863,7 +845,13 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         };
         let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() };
         let defaultness = hir::Defaultness::Default { has_value: has_default };
-        hir::TraitItemRef { id, ident: i.ident, span: i.span, defaultness, kind }
+        hir::TraitItemRef {
+            id,
+            ident: self.lower_ident(i.ident),
+            span: self.lower_span(i.span),
+            defaultness,
+            kind,
+        }
     }
 
     /// Construct `ExprKind::Err` for the given `span`.
@@ -894,7 +882,6 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
                     impl_item_def_id,
                     impl_trait_return_allow,
                     asyncness.opt_return_id(),
-                    i.id,
                 );
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
@@ -928,12 +915,12 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
         self.lower_attrs(hir_id, &i.attrs);
         hir::ImplItem {
             def_id: hir_id.expect_owner(),
-            ident: i.ident,
+            ident: self.lower_ident(i.ident),
             generics,
             vis: self.lower_visibility(&i.vis, None),
             defaultness,
             kind,
-            span: i.span,
+            span: self.lower_span(i.span),
         }
     }
 
@@ -943,8 +930,8 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         hir::ImplItemRef {
             id: hir::ImplItemId { def_id: self.lower_node_id(i.id).expect_owner() },
-            ident: i.ident,
-            span: i.span,
+            ident: self.lower_ident(i.ident),
+            span: self.lower_span(i.span),
             vis: self.lower_visibility(&i.vis, Some(i.id)),
             defaultness,
             kind: match &i.kind {
@@ -987,7 +974,7 @@ fn lower_visibility(
             }
             VisibilityKind::Inherited => hir::VisibilityKind::Inherited,
         };
-        respan(v.span, node)
+        respan(self.lower_span(v.span), node)
     }
 
     fn lower_defaultness(
@@ -996,7 +983,9 @@ fn lower_defaultness(
         has_value: bool,
     ) -> (hir::Defaultness, Option<Span>) {
         match d {
-            Defaultness::Default(sp) => (hir::Defaultness::Default { has_value }, Some(sp)),
+            Defaultness::Default(sp) => {
+                (hir::Defaultness::Default { has_value }, Some(self.lower_span(sp)))
+            }
             Defaultness::Final => {
                 assert!(has_value);
                 (hir::Defaultness::Final, None)
@@ -1034,8 +1023,8 @@ fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> {
         hir::Param {
             hir_id,
             pat: self.lower_pat(&param.pat),
-            ty_span: param.ty.span,
-            span: param.span,
+            ty_span: self.lower_span(param.ty.span),
+            span: self.lower_span(param.span),
         }
     }
 
@@ -1169,8 +1158,8 @@ fn lower_maybe_async_body(
                 let new_parameter = hir::Param {
                     hir_id: parameter.hir_id,
                     pat: new_parameter_pat,
-                    ty_span: parameter.ty_span,
-                    span: parameter.span,
+                    ty_span: this.lower_span(parameter.ty_span),
+                    span: this.lower_span(parameter.span),
                 };
 
                 if is_simple_parameter {
@@ -1287,9 +1276,8 @@ fn lower_method_sig(
         fn_def_id: LocalDefId,
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
-        id: NodeId,
     ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
-        let header = self.lower_fn_header(sig.header, sig.span, id);
+        let header = self.lower_fn_header(sig.header);
         let (generics, decl) = self.add_in_band_defs(
             generics,
             fn_def_id,
@@ -1303,15 +1291,15 @@ fn lower_method_sig(
                 )
             },
         );
-        (generics, hir::FnSig { header, decl, span: sig.span })
+        (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader, span: Span, id: NodeId) -> hir::FnHeader {
+    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         hir::FnHeader {
             unsafety: self.lower_unsafety(h.unsafety),
             asyncness: self.lower_asyncness(h.asyncness),
             constness: self.lower_constness(h.constness),
-            abi: self.lower_extern(h.ext, span, id),
+            abi: self.lower_extern(h.ext),
         }
     }
 
@@ -1322,13 +1310,10 @@ pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
         })
     }
 
-    pub(super) fn lower_extern(&mut self, ext: Extern, span: Span, id: NodeId) -> abi::Abi {
+    pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
         match ext {
             Extern::None => abi::Abi::Rust,
-            Extern::Implicit => {
-                self.maybe_lint_missing_abi(span, id, abi::Abi::C { unwind: false });
-                abi::Abi::C { unwind: false }
-            }
+            Extern::Implicit => abi::Abi::FALLBACK,
             Extern::Explicit(abi) => self.lower_abi(abi),
         }
     }
@@ -1403,7 +1388,7 @@ pub(super) fn lower_generics_mut(
         GenericsCtor {
             params: self.lower_generic_params_mut(&generics.params, &add_bounds, itctx).collect(),
             where_clause: self.lower_where_clause(&generics.where_clause),
-            span: generics.span,
+            span: self.lower_span(generics.span),
         }
     }
 
@@ -1422,7 +1407,7 @@ fn lower_where_clause(&mut self, wc: &WhereClause) -> hir::WhereClause<'hir> {
                 predicates: this.arena.alloc_from_iter(
                     wc.predicates.iter().map(|predicate| this.lower_where_predicate(predicate)),
                 ),
-                span: wc.span,
+                span: this.lower_span(wc.span),
             }
         })
     }
@@ -1451,12 +1436,12 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                                 // `suggest_constraining_type_param`. This will need to change if
                                 // we ever allow something *other* than `?Sized`.
                                 GenericBound::Trait(p, TraitBoundModifier::Maybe) => {
-                                    hir::GenericBound::Unsized(p.span)
+                                    hir::GenericBound::Unsized(this.lower_span(p.span))
                                 }
                                 _ => this.lower_param_bound(bound, ImplTraitContext::disallowed()),
                             },
                         )),
-                        span,
+                        span: this.lower_span(span),
                     })
                 })
             }
@@ -1465,7 +1450,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                 ref bounds,
                 span,
             }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                span,
+                span: self.lower_span(span),
                 lifetime: self.lower_lifetime(lifetime),
                 bounds: self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
             }),
@@ -1474,7 +1459,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
                     hir_id: self.lower_node_id(id),
                     lhs_ty: self.lower_ty(lhs_ty, ImplTraitContext::disallowed()),
                     rhs_ty: self.lower_ty(rhs_ty, ImplTraitContext::disallowed()),
-                    span,
+                    span: self.lower_span(span),
                 })
             }
         }
index 7b0188755710bc0825d4cda8d3af5e83f10f14d0..5391d4b0c93638295cfe30fccc84afef52507dc2 100644 (file)
@@ -39,7 +39,6 @@
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::walk_list;
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName};
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
+use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
 use rustc_session::Session;
 use rustc_span::source_map::{respan, CachingSourceMapView, DesugaringKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::spec::abi::Abi;
 
-use smallvec::{smallvec, SmallVec};
+use smallvec::SmallVec;
 use std::collections::BTreeMap;
-use std::mem;
 use tracing::{debug, trace};
 
 macro_rules! arena_vec {
@@ -77,6 +74,7 @@ macro_rules! arena_vec {
 }
 
 mod asm;
+mod block;
 mod expr;
 mod item;
 mod pat;
@@ -84,7 +82,7 @@ macro_rules! arena_vec {
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
-rustc_hir::arena_types!(rustc_arena::declare_arena, [], 'tcx);
+rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
 
 struct LoweringContext<'a, 'hir: 'a> {
     /// Used to assign IDs to HIR nodes that do not directly correspond to AST nodes.
@@ -103,9 +101,6 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// The items being lowered are collected here.
     owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
     bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
-    non_exported_macro_attrs: Vec<ast::Attribute>,
-
-    trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
 
     modules: BTreeMap<LocalDefId, hir::ModuleItems>,
 
@@ -121,8 +116,8 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// outside of an `async fn`.
     current_item: Option<Span>,
 
-    catch_scopes: Vec<NodeId>,
-    loop_scopes: Vec<NodeId>,
+    catch_scope: Option<NodeId>,
+    loop_scope: Option<NodeId>,
     is_in_loop_condition: bool,
     is_in_trait_impl: bool,
     is_in_dyn_type: bool,
@@ -159,8 +154,6 @@ struct LoweringContext<'a, 'hir: 'a> {
 
     current_module: LocalDefId,
 
-    type_def_lifetime_params: DefIdMap<usize>,
-
     current_hir_id_owner: (LocalDefId, u32),
     item_local_id_counters: NodeMap<u32>,
     node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
@@ -172,7 +165,7 @@ struct LoweringContext<'a, 'hir: 'a> {
 pub trait ResolverAstLowering {
     fn def_key(&mut self, id: DefId) -> DefKey;
 
-    fn item_generics_num_lifetimes(&self, def: DefId, sess: &Session) -> usize;
+    fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
 
     fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
 
@@ -327,17 +320,14 @@ pub fn lower_crate<'a, 'hir>(
         arena,
         owners: IndexVec::default(),
         bodies: BTreeMap::new(),
-        trait_impls: BTreeMap::new(),
         modules: BTreeMap::new(),
         attrs: BTreeMap::default(),
-        non_exported_macro_attrs: Vec::new(),
-        catch_scopes: Vec::new(),
-        loop_scopes: Vec::new(),
+        catch_scope: None,
+        loop_scope: None,
         is_in_loop_condition: false,
         is_in_trait_impl: false,
         is_in_dyn_type: false,
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
-        type_def_lifetime_params: Default::default(),
         current_module: CRATE_DEF_ID,
         current_hir_id_owner: (CRATE_DEF_ID, 0),
         item_local_id_counters: Default::default(),
@@ -453,26 +443,8 @@ impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
             fn visit_item(&mut self, item: &'tcx Item) {
                 self.lctx.allocate_hir_id_counter(item.id);
 
-                match item.kind {
-                    ItemKind::Struct(_, ref generics)
-                    | ItemKind::Union(_, ref generics)
-                    | ItemKind::Enum(_, ref generics)
-                    | ItemKind::TyAlias(box TyAliasKind(_, ref generics, ..))
-                    | ItemKind::Trait(box TraitKind(_, _, ref generics, ..)) => {
-                        let def_id = self.lctx.resolver.local_def_id(item.id);
-                        let count = generics
-                            .params
-                            .iter()
-                            .filter(|param| {
-                                matches!(param.kind, ast::GenericParamKind::Lifetime { .. })
-                            })
-                            .count();
-                        self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count);
-                    }
-                    ItemKind::Use(ref use_tree) => {
-                        self.allocate_use_tree_hir_id_counters(use_tree);
-                    }
-                    _ => {}
+                if let ItemKind::Use(ref use_tree) = item.kind {
+                    self.allocate_use_tree_hir_id_counters(use_tree);
                 }
 
                 visit::walk_item(self, item);
@@ -487,23 +459,6 @@ fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
                 self.lctx.allocate_hir_id_counter(item.id);
                 visit::walk_foreign_item(self, item);
             }
-
-            fn visit_ty(&mut self, t: &'tcx Ty) {
-                match t.kind {
-                    // Mirrors the case in visit::walk_ty
-                    TyKind::BareFn(ref f) => {
-                        walk_list!(self, visit_generic_param, &f.generic_params);
-                        // Mirrors visit::walk_fn_decl
-                        for parameter in &f.decl.inputs {
-                            // We don't lower the ids of argument patterns
-                            self.visit_pat(&parameter.pat);
-                            self.visit_ty(&parameter.ty)
-                        }
-                        self.visit_fn_ret_ty(&f.decl.output)
-                    }
-                    _ => visit::walk_ty(self, t),
-                }
-            }
         }
 
         self.lower_node_id(CRATE_NODE_ID);
@@ -517,10 +472,6 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
         self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
 
-        let body_ids = body_ids(&self.bodies);
-        let proc_macros =
-            c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
-
         let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
         for (k, v) in self.resolver.take_trait_map().into_iter() {
             if let Some(Some(hir_id)) = self.node_id_to_hir_id.get(k) {
@@ -551,13 +502,9 @@ fn visit_ty(&mut self, t: &'tcx Ty) {
         }
 
         let krate = hir::Crate {
-            non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
             owners: self.owners,
             bodies: self.bodies,
-            body_ids,
-            trait_impls: self.trait_impls,
             modules: self.modules,
-            proc_macros,
             trait_map,
             attrs: self.attrs,
         };
@@ -600,13 +547,6 @@ fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId
         id
     }
 
-    fn insert_macro_def(&mut self, item: hir::MacroDef<'hir>) {
-        let def_id = item.def_id;
-        let item = self.arena.alloc(item);
-        self.owners.ensure_contains_elem(def_id, || None);
-        self.owners[def_id] = Some(hir::OwnerNode::MacroDef(item));
-    }
-
     fn allocate_hir_id_counter(&mut self, owner: NodeId) -> hir::HirId {
         // Set up the counter if needed.
         self.item_local_id_counters.entry(owner).or_insert(0);
@@ -770,6 +710,16 @@ fn with_anonymous_lifetime_mode<R>(
         result
     }
 
+    /// Intercept all spans entering HIR.
+    /// For now we are not doing anything with the intercepted spans.
+    fn lower_span(&self, span: Span) -> Span {
+        span
+    }
+
+    fn lower_ident(&self, ident: Ident) -> Ident {
+        Ident::new(ident.name, self.lower_span(ident.span))
+    }
+
     /// Creates a new `hir::GenericParam` for every new lifetime and
     /// type parameter encountered while evaluating `f`. Definitions
     /// are created with the parent provided. If no `parent_id` is
@@ -838,7 +788,7 @@ fn lifetime_to_generic_param(
             hir_id: self.lower_node_id(node_id),
             name: hir_name,
             bounds: &[],
-            span,
+            span: self.lower_span(span),
             pure_wrt_drop: false,
             kind: hir::GenericParamKind::Lifetime { kind },
         }
@@ -960,11 +910,11 @@ fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
-        let catch_scopes = mem::take(&mut self.catch_scopes);
-        let loop_scopes = mem::take(&mut self.loop_scopes);
+        let catch_scope = self.catch_scope.take();
+        let loop_scope = self.loop_scope.take();
         let ret = f(self);
-        self.catch_scopes = catch_scopes;
-        self.loop_scopes = loop_scopes;
+        self.catch_scope = catch_scope;
+        self.loop_scope = loop_scope;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
@@ -999,7 +949,7 @@ fn lower_attr(&self, attr: &Attribute) -> Attribute {
             AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data),
         };
 
-        Attribute { kind, id: attr.id, style: attr.style, span: attr.span }
+        Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
     }
 
     fn alias_attrs(&mut self, id: hir::HirId, target_id: hir::HirId) {
@@ -1127,7 +1077,7 @@ fn lower_assoc_ty_constraint(
                     .0
                 }
             };
-            self.arena.alloc(gen_args_ctor.into_generic_args(&self.arena))
+            gen_args_ctor.into_generic_args(self)
         } else {
             self.arena.alloc(hir::GenericArgs::none())
         };
@@ -1208,7 +1158,7 @@ fn lower_assoc_ty_constraint(
                             &Ty {
                                 id: node_id,
                                 kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
-                                span: constraint.span,
+                                span: this.lower_span(constraint.span),
                                 tokens: None,
                             },
                             itctx,
@@ -1228,10 +1178,10 @@ fn lower_assoc_ty_constraint(
 
         hir::TypeBinding {
             hir_id: self.lower_node_id(constraint.id),
-            ident: constraint.ident,
+            ident: self.lower_ident(constraint.ident),
             gen_args,
             kind,
-            span: constraint.span,
+            span: self.lower_span(constraint.span),
         }
     }
 
@@ -1245,10 +1195,9 @@ fn lower_generic_arg(
             ast::GenericArg::Type(ty) => {
                 match ty.kind {
                     TyKind::Infer if self.sess.features_untracked().generic_arg_infer => {
-                        let hir_id = self.lower_node_id(ty.id);
                         return GenericArg::Infer(hir::InferArg {
-                            hir_id,
-                            span: ty.span,
+                            hir_id: self.lower_node_id(ty.id),
+                            span: self.lower_span(ty.span),
                             kind: InferKind::Type,
                         });
                     }
@@ -1279,10 +1228,11 @@ fn lower_generic_arg(
                                     ty.span,
                                 );
 
+                                let span = self.lower_span(ty.span);
                                 let path_expr = Expr {
                                     id: ty.id,
                                     kind: ExprKind::Path(qself.clone(), path.clone()),
-                                    span: ty.span,
+                                    span,
                                     attrs: AttrVec::new(),
                                     tokens: None,
                                 };
@@ -1291,7 +1241,7 @@ fn lower_generic_arg(
                                     hir_id: this.lower_node_id(node_id),
                                     body: this.lower_const_body(path_expr.span, Some(&path_expr)),
                                 });
-                                return GenericArg::Const(ConstArg { value: ct, span: ty.span });
+                                return GenericArg::Const(ConstArg { value: ct, span });
                             }
                         }
                     }
@@ -1301,7 +1251,7 @@ fn lower_generic_arg(
             }
             ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
                 value: self.lower_anon_const(&ct),
-                span: ct.value.span,
+                span: self.lower_span(ct.value.span),
             }),
         }
     }
@@ -1328,7 +1278,7 @@ fn lower_path_ty(
     }
 
     fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> {
-        hir::Ty { hir_id: self.next_id(), kind, span }
+        hir::Ty { hir_id: self.next_id(), kind, span: self.lower_span(span) }
     }
 
     fn ty_tup(&mut self, span: Span, tys: &'hir [hir::Ty<'hir>]) -> hir::Ty<'hir> {
@@ -1360,7 +1310,6 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
             }
             TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
                 this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
-                    let span = this.sess.source_map().next_point(t.span.shrink_to_lo());
                     hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
@@ -1368,7 +1317,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                             ImplTraitContext::disallowed(),
                         ),
                         unsafety: this.lower_unsafety(f.unsafety),
-                        abi: this.lower_extern(f.ext, span, t.id),
+                        abi: this.lower_extern(f.ext),
                         decl: this.lower_fn_decl(&f.decl, None, false, None),
                         param_names: this.lower_fn_params_to_names(&f.decl),
                     }))
@@ -1396,7 +1345,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                         segments: arena_vec![self; hir::PathSegment::from_ident(
                             Ident::with_dummy_span(kw::SelfUpper)
                         )],
-                        span: t.span,
+                        span: self.lower_span(t.span),
                     }),
                 ))
             }
@@ -1414,7 +1363,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                                     ref ty,
                                     TraitBoundModifier::None | TraitBoundModifier::MaybeConst,
                                 ) => Some(this.lower_poly_trait_ref(ty, itctx.reborrow())),
-                                // `?const ?Bound` will cause an error during AST validation
+                                // `~const ?Bound` will cause an error during AST validation
                                 // anyways, so treat it like `?Bound` as compilation proceeds.
                                 GenericBound::Trait(
                                     _,
@@ -1477,10 +1426,10 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                         let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
                         in_band_ty_params.push(hir::GenericParam {
                             hir_id: self.lower_node_id(def_node_id),
-                            name: ParamName::Plain(ident),
+                            name: ParamName::Plain(self.lower_ident(ident)),
                             pure_wrt_drop: false,
                             bounds: hir_bounds,
-                            span,
+                            span: self.lower_span(span),
                             kind: hir::GenericParamKind::Type {
                                 default: None,
                                 synthetic: Some(hir::SyntheticTyParamKind::ImplTrait),
@@ -1490,9 +1439,9 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
                         hir::TyKind::Path(hir::QPath::Resolved(
                             None,
                             self.arena.alloc(hir::Path {
-                                span,
+                                span: self.lower_span(span),
                                 res: Res::Def(DefKind::TyParam, def_id.to_def_id()),
-                                segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+                                segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
                             }),
                         ))
                     }
@@ -1519,7 +1468,7 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
             }
         };
 
-        hir::Ty { kind, span: t.span, hir_id: self.lower_node_id(t.id) }
+        hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) }
     }
 
     fn lower_opaque_impl_trait(
@@ -1547,25 +1496,55 @@ fn lower_opaque_impl_trait(
 
         self.allocate_hir_id_counter(opaque_ty_node_id);
 
-        let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
+        let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
+            let hir_bounds = lower_bounds(lctx);
 
-        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
-            opaque_ty_node_id,
-            opaque_ty_def_id,
-            &hir_bounds,
-            capturable_lifetimes,
-        );
+            let collected_lifetimes = lifetimes_from_impl_trait_bounds(
+                opaque_ty_node_id,
+                &hir_bounds,
+                capturable_lifetimes,
+            );
 
-        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
+            let lifetime_defs =
+                lctx.arena.alloc_from_iter(collected_lifetimes.iter().map(|&(name, span)| {
+                    let def_node_id = lctx.resolver.next_node_id();
+                    let hir_id = lctx.lower_node_id(def_node_id);
+                    lctx.resolver.create_def(
+                        opaque_ty_def_id,
+                        def_node_id,
+                        DefPathData::LifetimeNs(name.ident().name),
+                        ExpnId::root(),
+                        span,
+                    );
 
-        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
+                    let (name, kind) = match name {
+                        hir::LifetimeName::Underscore => (
+                            hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
+                            hir::LifetimeParamKind::Elided,
+                        ),
+                        hir::LifetimeName::Param(param_name) => {
+                            (param_name, hir::LifetimeParamKind::Explicit)
+                        }
+                        _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"),
+                    };
+
+                    hir::GenericParam {
+                        hir_id,
+                        name,
+                        span,
+                        pure_wrt_drop: false,
+                        bounds: &[],
+                        kind: hir::GenericParamKind::Lifetime { kind },
+                    }
+                }));
+
+            debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
 
-        self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
                     params: lifetime_defs,
-                    where_clause: hir::WhereClause { predicates: &[], span },
-                    span,
+                    where_clause: hir::WhereClause { predicates: &[], span: lctx.lower_span(span) },
+                    span: lctx.lower_span(span),
                 },
                 bounds: hir_bounds,
                 impl_trait_fn: fn_def_id,
@@ -1575,9 +1554,18 @@ fn lower_opaque_impl_trait(
             trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
             lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
 
-            // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-            hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
-        })
+            collected_lifetimes
+        });
+
+        let lifetimes =
+            self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(name, span)| {
+                hir::GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span, name })
+            }));
+
+        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
+
+        // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
+        hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
     }
 
     /// Registers a new opaque type with the proper `NodeId`s and
@@ -1596,8 +1584,8 @@ fn generate_opaque_type(
             def_id: opaque_ty_id,
             ident: Ident::invalid(),
             kind: opaque_ty_item_kind,
-            vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited),
-            span: opaque_ty_span,
+            vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
+            span: self.lower_span(opaque_ty_span),
         };
 
         // Insert the item into the global item list. This usually happens
@@ -1606,205 +1594,6 @@ fn generate_opaque_type(
         self.insert_item(opaque_ty_item);
     }
 
-    fn lifetimes_from_impl_trait_bounds(
-        &mut self,
-        opaque_ty_id: NodeId,
-        parent_def_id: LocalDefId,
-        bounds: hir::GenericBounds<'hir>,
-        lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
-    ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
-        debug!(
-            "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
-             parent_def_id={:?}, \
-             bounds={:#?})",
-            opaque_ty_id, parent_def_id, bounds,
-        );
-
-        // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
-        // appear in the bounds, excluding lifetimes that are created within the bounds.
-        // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
-        struct ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            context: &'r mut LoweringContext<'a, 'hir>,
-            parent: LocalDefId,
-            opaque_ty_id: NodeId,
-            collect_elided_lifetimes: bool,
-            currently_bound_lifetimes: Vec<hir::LifetimeName>,
-            already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
-            output_lifetimes: Vec<hir::GenericArg<'hir>>,
-            output_lifetime_params: Vec<hir::GenericParam<'hir>>,
-            lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
-        }
-
-        impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
-            type Map = intravisit::ErasedMap<'v>;
-
-            fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-                intravisit::NestedVisitorMap::None
-            }
-
-            fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
-                // Don't collect elided lifetimes used inside of `Fn()` syntax.
-                if parameters.parenthesized {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-                    intravisit::walk_generic_args(self, span, parameters);
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    intravisit::walk_generic_args(self, span, parameters);
-                }
-            }
-
-            fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
-                // Don't collect elided lifetimes used inside of `fn()` syntax.
-                if let hir::TyKind::BareFn(_) = t.kind {
-                    let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
-                    self.collect_elided_lifetimes = false;
-
-                    // Record the "stack height" of `for<'a>` lifetime bindings
-                    // to be able to later fully undo their introduction.
-                    let old_len = self.currently_bound_lifetimes.len();
-                    intravisit::walk_ty(self, t);
-                    self.currently_bound_lifetimes.truncate(old_len);
-
-                    self.collect_elided_lifetimes = old_collect_elided_lifetimes;
-                } else {
-                    intravisit::walk_ty(self, t)
-                }
-            }
-
-            fn visit_poly_trait_ref(
-                &mut self,
-                trait_ref: &'v hir::PolyTraitRef<'v>,
-                modifier: hir::TraitBoundModifier,
-            ) {
-                // Record the "stack height" of `for<'a>` lifetime bindings
-                // to be able to later fully undo their introduction.
-                let old_len = self.currently_bound_lifetimes.len();
-                intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
-                self.currently_bound_lifetimes.truncate(old_len);
-            }
-
-            fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
-                // Record the introduction of 'a in `for<'a> ...`.
-                if let hir::GenericParamKind::Lifetime { .. } = param.kind {
-                    // Introduce lifetimes one at a time so that we can handle
-                    // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
-                    let lt_name = hir::LifetimeName::Param(param.name);
-                    self.currently_bound_lifetimes.push(lt_name);
-                }
-
-                intravisit::walk_generic_param(self, param);
-            }
-
-            fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
-                let name = match lifetime.name {
-                    hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
-                        if self.collect_elided_lifetimes {
-                            // Use `'_` for both implicit and underscore lifetimes in
-                            // `type Foo<'_> = impl SomeTrait<'_>;`.
-                            hir::LifetimeName::Underscore
-                        } else {
-                            return;
-                        }
-                    }
-                    hir::LifetimeName::Param(_) => lifetime.name,
-
-                    // Refers to some other lifetime that is "in
-                    // scope" within the type.
-                    hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
-
-                    hir::LifetimeName::Error | hir::LifetimeName::Static => return,
-                };
-
-                if !self.currently_bound_lifetimes.contains(&name)
-                    && !self.already_defined_lifetimes.contains(&name)
-                    && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
-                {
-                    self.already_defined_lifetimes.insert(name);
-
-                    self.output_lifetimes.push(hir::GenericArg::Lifetime(hir::Lifetime {
-                        hir_id: self.context.next_id(),
-                        span: lifetime.span,
-                        name,
-                    }));
-
-                    let def_node_id = self.context.resolver.next_node_id();
-                    let hir_id =
-                        self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id);
-                    self.context.resolver.create_def(
-                        self.parent,
-                        def_node_id,
-                        DefPathData::LifetimeNs(name.ident().name),
-                        ExpnId::root(),
-                        lifetime.span,
-                    );
-
-                    let (name, kind) = match name {
-                        hir::LifetimeName::Underscore => (
-                            hir::ParamName::Plain(Ident::with_dummy_span(kw::UnderscoreLifetime)),
-                            hir::LifetimeParamKind::Elided,
-                        ),
-                        hir::LifetimeName::Param(param_name) => {
-                            (param_name, hir::LifetimeParamKind::Explicit)
-                        }
-                        _ => panic!("expected `LifetimeName::Param` or `ParamName::Plain`"),
-                    };
-
-                    self.output_lifetime_params.push(hir::GenericParam {
-                        hir_id,
-                        name,
-                        span: lifetime.span,
-                        pure_wrt_drop: false,
-                        bounds: &[],
-                        kind: hir::GenericParamKind::Lifetime { kind },
-                    });
-                }
-            }
-        }
-
-        let mut lifetime_collector = ImplTraitLifetimeCollector {
-            context: self,
-            parent: parent_def_id,
-            opaque_ty_id,
-            collect_elided_lifetimes: true,
-            currently_bound_lifetimes: Vec::new(),
-            already_defined_lifetimes: FxHashSet::default(),
-            output_lifetimes: Vec::new(),
-            output_lifetime_params: Vec::new(),
-            lifetimes_to_include,
-        };
-
-        for bound in bounds {
-            intravisit::walk_param_bound(&mut lifetime_collector, &bound);
-        }
-
-        let ImplTraitLifetimeCollector { output_lifetimes, output_lifetime_params, .. } =
-            lifetime_collector;
-
-        (
-            self.arena.alloc_from_iter(output_lifetimes),
-            self.arena.alloc_from_iter(output_lifetime_params),
-        )
-    }
-
-    fn lower_local(&mut self, l: &Local) -> hir::Local<'hir> {
-        let ty = l
-            .ty
-            .as_ref()
-            .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
-        let init = l.init.as_ref().map(|e| self.lower_expr(e));
-        let hir_id = self.lower_node_id(l.id);
-        self.lower_attrs(hir_id, &l.attrs);
-        hir::Local {
-            hir_id,
-            ty,
-            pat: self.lower_pat(&l.pat),
-            init,
-            span: l.span,
-            source: hir::LocalSource::Normal,
-        }
-    }
-
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
         // Skip the `...` (`CVarArgs`) trailing arguments from the AST,
         // as they are not explicit in HIR/Ty function signatures.
@@ -1814,8 +1603,8 @@ fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
             inputs = &inputs[..inputs.len() - 1];
         }
         self.arena.alloc_from_iter(inputs.iter().map(|param| match param.pat.kind {
-            PatKind::Ident(_, ident, _) => ident,
-            _ => Ident::new(kw::Empty, param.pat.span),
+            PatKind::Ident(_, ident, _) => self.lower_ident(ident),
+            _ => Ident::new(kw::Empty, self.lower_span(param.pat.span)),
         }))
     }
 
@@ -1899,7 +1688,7 @@ fn lower_fn_decl(
                     };
                     hir::FnRetTy::Return(self.lower_ty(ty, context))
                 }
-                FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(span),
+                FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
             }
         };
 
@@ -2056,8 +1845,8 @@ fn lower_async_fn_ret_ty(
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
                     params: generic_params,
-                    where_clause: hir::WhereClause { predicates: &[], span },
-                    span,
+                    where_clause: hir::WhereClause { predicates: &[], span: this.lower_span(span) },
+                    span: this.lower_span(span),
                 },
                 bounds: arena_vec![this; future_bound],
                 impl_trait_fn: Some(fn_def_id),
@@ -2092,7 +1881,7 @@ fn lower_async_fn_ret_ty(
                 // Input lifetime like `'a` or `'1`:
                 GenericArg::Lifetime(hir::Lifetime {
                     hir_id: self.next_id(),
-                    span,
+                    span: self.lower_span(span),
                     name: hir::LifetimeName::Param(hir_name),
                 })
             },
@@ -2101,7 +1890,7 @@ fn lower_async_fn_ret_ty(
             // Output lifetime like `'_`.
             GenericArg::Lifetime(hir::Lifetime {
                 hir_id: self.next_id(),
-                span,
+                span: self.lower_span(span),
                 name: hir::LifetimeName::Implicit,
             })));
         let generic_args = self.arena.alloc_from_iter(generic_args);
@@ -2149,7 +1938,7 @@ fn lower_async_fn_output_type_to_future_bound(
         hir::GenericBound::LangItemTrait(
             // ::std::future::Future<future_params>
             hir::LangItem::Future,
-            span,
+            self.lower_span(span),
             self.next_id(),
             future_args,
         )
@@ -2172,7 +1961,7 @@ fn lower_param_bound(
     }
 
     fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
-        let span = l.ident.span;
+        let span = self.lower_span(l.ident.span);
         match l.ident {
             ident if ident.name == kw::StaticLifetime => {
                 self.new_named_lifetime(l.id, span, hir::LifetimeName::Static)
@@ -2191,7 +1980,7 @@ fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
             },
             ident => {
                 self.maybe_collect_in_band_lifetime(ident);
-                let param_name = ParamName::Plain(ident);
+                let param_name = ParamName::Plain(self.lower_ident(ident));
                 self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name))
             }
         }
@@ -2203,7 +1992,7 @@ fn new_named_lifetime(
         span: Span,
         name: hir::LifetimeName,
     ) -> hir::Lifetime {
-        hir::Lifetime { hir_id: self.lower_node_id(id), span, name }
+        hir::Lifetime { hir_id: self.lower_node_id(id), span: self.lower_span(span), name }
     }
 
     fn lower_generic_params_mut<'s>(
@@ -2286,7 +2075,7 @@ fn lower_generic_param(
                         .next(),
                 };
 
-                (hir::ParamName::Plain(param.ident), kind)
+                (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
             }
             GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                 let ty = self
@@ -2294,16 +2083,23 @@ fn lower_generic_param(
                         this.lower_ty(&ty, ImplTraitContext::disallowed())
                     });
                 let default = default.as_ref().map(|def| self.lower_anon_const(def));
-                (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
+                (
+                    hir::ParamName::Plain(self.lower_ident(param.ident)),
+                    hir::GenericParamKind::Const { ty, default },
+                )
             }
         };
+        let name = match name {
+            hir::ParamName::Plain(ident) => hir::ParamName::Plain(self.lower_ident(ident)),
+            name => name,
+        };
 
         let hir_id = self.lower_node_id(param.id);
         self.lower_attrs(hir_id, &param.attrs);
         hir::GenericParam {
             hir_id,
             name,
-            span: param.ident.span,
+            span: self.lower_span(param.ident.span),
             pure_wrt_drop: self.sess.contains_name(&param.attrs, sym::may_dangle),
             bounds: self.arena.alloc_from_iter(bounds),
             kind,
@@ -2360,7 +2156,7 @@ fn lower_poly_trait_ref(
             res
         });
 
-        hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
+        hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
     }
 
     fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_, 'hir>) -> hir::MutTy<'hir> {
@@ -2383,23 +2179,6 @@ fn lower_param_bounds_mut<'s>(
         bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx.reborrow()))
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> &'hir hir::Block<'hir> {
-        self.arena.alloc(self.lower_block_noalloc(b, targeted_by_break))
-    }
-
-    fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
-        let (stmts, expr) = match &*b.stmts {
-            [stmts @ .., Stmt { kind: StmtKind::Expr(e), .. }] => (stmts, Some(&*e)),
-            stmts => (stmts, None),
-        };
-        let stmts = self.arena.alloc_from_iter(stmts.iter().flat_map(|stmt| self.lower_stmt(stmt)));
-        let expr = expr.map(|e| self.lower_expr(e));
-        let rules = self.lower_block_check_mode(&b.rules);
-        let hir_id = self.lower_node_id(b.id);
-
-        hir::Block { hir_id, stmts, expr, rules, span: b.span, targeted_by_break }
-    }
-
     /// Lowers a block directly to an expression, presuming that it
     /// has no attributes and is not targeted by a `break`.
     fn lower_block_expr(&mut self, b: &Block) -> hir::Expr<'hir> {
@@ -2414,61 +2193,6 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         })
     }
 
-    fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> {
-        let (hir_id, kind) = match s.kind {
-            StmtKind::Local(ref l) => {
-                let l = self.lower_local(l);
-                let hir_id = self.lower_node_id(s.id);
-                self.alias_attrs(hir_id, l.hir_id);
-                return smallvec![hir::Stmt {
-                    hir_id,
-                    kind: hir::StmtKind::Local(self.arena.alloc(l)),
-                    span: s.span,
-                }];
-            }
-            StmtKind::Item(ref it) => {
-                // Can only use the ID once.
-                let mut id = Some(s.id);
-                return self
-                    .lower_item_id(it)
-                    .into_iter()
-                    .map(|item_id| {
-                        let hir_id = id
-                            .take()
-                            .map(|id| self.lower_node_id(id))
-                            .unwrap_or_else(|| self.next_id());
-
-                        hir::Stmt { hir_id, kind: hir::StmtKind::Item(item_id), span: s.span }
-                    })
-                    .collect();
-            }
-            StmtKind::Expr(ref e) => {
-                let e = self.lower_expr(e);
-                let hir_id = self.lower_node_id(s.id);
-                self.alias_attrs(hir_id, e.hir_id);
-                (hir_id, hir::StmtKind::Expr(e))
-            }
-            StmtKind::Semi(ref e) => {
-                let e = self.lower_expr(e);
-                let hir_id = self.lower_node_id(s.id);
-                self.alias_attrs(hir_id, e.hir_id);
-                (hir_id, hir::StmtKind::Semi(e))
-            }
-            StmtKind::Empty => return smallvec![],
-            StmtKind::MacCall(..) => panic!("shouldn't exist here"),
-        };
-        smallvec![hir::Stmt { hir_id, kind, span: s.span }]
-    }
-
-    fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode {
-        match *b {
-            BlockCheckMode::Default => hir::BlockCheckMode::DefaultBlock,
-            BlockCheckMode::Unsafe(u) => {
-                hir::BlockCheckMode::UnsafeBlock(self.lower_unsafe_source(u))
-            }
-        }
-    }
-
     fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource {
         match u {
             CompilerGenerated => hir::UnsafeSource::CompilerGenerated,
@@ -2492,7 +2216,7 @@ fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBou
     // Helper methods for building HIR.
 
     fn stmt(&mut self, span: Span, kind: hir::StmtKind<'hir>) -> hir::Stmt<'hir> {
-        hir::Stmt { span, kind, hir_id: self.next_id() }
+        hir::Stmt { span: self.lower_span(span), kind, hir_id: self.next_id() }
     }
 
     fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> {
@@ -2512,7 +2236,7 @@ fn stmt_let_pat(
             debug_assert!(!a.is_empty());
             self.attrs.insert(hir_id, a);
         }
-        let local = hir::Local { hir_id, init, pat, source, span, ty: None };
+        let local = hir::Local { hir_id, init, pat, source, span: self.lower_span(span), ty: None };
         self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local)))
     }
 
@@ -2531,7 +2255,7 @@ fn block_all(
             expr,
             hir_id: self.next_id(),
             rules: hir::BlockCheckMode::DefaultBlock,
-            span,
+            span: self.lower_span(span),
             targeted_by_break: false,
         };
         self.arena.alloc(blk)
@@ -2563,10 +2287,10 @@ fn single_pat_field(
     ) -> &'hir [hir::PatField<'hir>] {
         let field = hir::PatField {
             hir_id: self.next_id(),
-            ident: Ident::new(sym::integer(0), span),
+            ident: Ident::new(sym::integer(0), self.lower_span(span)),
             is_shorthand: false,
             pat,
-            span,
+            span: self.lower_span(span),
         };
         arena_vec![self; field]
     }
@@ -2577,7 +2301,7 @@ fn pat_lang_item_variant(
         lang_item: hir::LangItem,
         fields: &'hir [hir::PatField<'hir>],
     ) -> &'hir hir::Pat<'hir> {
-        let qpath = hir::QPath::LangItem(lang_item, span);
+        let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span));
         self.pat(span, hir::PatKind::Struct(qpath, fields, false))
     }
 
@@ -2610,8 +2334,8 @@ fn pat_ident_binding_mode_mut(
         (
             hir::Pat {
                 hir_id,
-                kind: hir::PatKind::Binding(bm, hir_id, ident.with_span_pos(span), None),
-                span,
+                kind: hir::PatKind::Binding(bm, hir_id, self.lower_ident(ident), None),
+                span: self.lower_span(span),
                 default_binding_modes: true,
             },
             hir_id,
@@ -2622,13 +2346,18 @@ fn pat(&mut self, span: Span, kind: hir::PatKind<'hir>) -> &'hir hir::Pat<'hir>
         self.arena.alloc(hir::Pat {
             hir_id: self.next_id(),
             kind,
-            span,
+            span: self.lower_span(span),
             default_binding_modes: true,
         })
     }
 
     fn pat_without_dbm(&mut self, span: Span, kind: hir::PatKind<'hir>) -> hir::Pat<'hir> {
-        hir::Pat { hir_id: self.next_id(), kind, span, default_binding_modes: false }
+        hir::Pat {
+            hir_id: self.next_id(),
+            kind,
+            span: self.lower_span(span),
+            default_binding_modes: false,
+        }
     }
 
     fn ty_path(
@@ -2645,7 +2374,7 @@ fn ty_path(
                         let principal = hir::PolyTraitRef {
                             bound_generic_params: &[],
                             trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
-                            span,
+                            span: self.lower_span(span),
                         };
 
                         // The original ID is taken by the `PolyTraitRef`,
@@ -2663,7 +2392,7 @@ fn ty_path(
             _ => hir::TyKind::Path(qpath),
         };
 
-        hir::Ty { hir_id, kind, span }
+        hir::Ty { hir_id, kind, span: self.lower_span(span) }
     }
 
     /// Invoked to create the lifetime argument for a type `&T`
@@ -2678,7 +2407,7 @@ fn elided_ref_lifetime(&mut self, span: Span) -> hir::Lifetime {
                 let fresh_name = self.collect_fresh_in_band_lifetime(span);
                 hir::Lifetime {
                     hir_id: self.next_id(),
-                    span,
+                    span: self.lower_span(span),
                     name: hir::LifetimeName::Param(fresh_name),
                 }
             }
@@ -2773,7 +2502,7 @@ fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
 
         let r = hir::Lifetime {
             hir_id: self.next_id(),
-            span,
+            span: self.lower_span(span),
             name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
         };
         debug!("elided_dyn_bound: r={:?}", r);
@@ -2781,7 +2510,11 @@ fn elided_dyn_bound(&mut self, span: Span) -> hir::Lifetime {
     }
 
     fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {
-        hir::Lifetime { hir_id: self.next_id(), span, name: hir::LifetimeName::Implicit }
+        hir::Lifetime {
+            hir_id: self.next_id(),
+            span: self.lower_span(span),
+            name: hir::LifetimeName::Implicit,
+        }
     }
 
     fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) {
@@ -2816,34 +2549,6 @@ fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) {
             }
         }
     }
-
-    fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId, default: Abi) {
-        // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
-        // call site which do not have a macro backtrace. See #61963.
-        let is_macro_callsite = self
-            .sess
-            .source_map()
-            .span_to_snippet(span)
-            .map(|snippet| snippet.starts_with("#["))
-            .unwrap_or(true);
-        if !is_macro_callsite {
-            self.resolver.lint_buffer().buffer_lint_with_diagnostic(
-                MISSING_ABI,
-                id,
-                span,
-                "extern declarations without an explicit ABI are deprecated",
-                BuiltinLintDiagnostics::MissingAbi(span, default),
-            )
-        }
-    }
-}
-
-fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
-    // Sorting by span ensures that we get things in order within a
-    // file, and also puts the files in a sensible order.
-    let mut body_ids: Vec<_> = bodies.keys().cloned().collect();
-    body_ids.sort_by_key(|b| bodies[b].value.span);
-    body_ids
 }
 
 /// Helper struct for delayed construction of GenericArgs.
@@ -2859,12 +2564,142 @@ fn is_empty(&self) -> bool {
         self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
     }
 
-    fn into_generic_args(self, arena: &'hir Arena<'hir>) -> hir::GenericArgs<'hir> {
-        hir::GenericArgs {
-            args: arena.alloc_from_iter(self.args),
+    fn into_generic_args(self, this: &LoweringContext<'_, 'hir>) -> &'hir hir::GenericArgs<'hir> {
+        let ga = hir::GenericArgs {
+            args: this.arena.alloc_from_iter(self.args),
             bindings: self.bindings,
             parenthesized: self.parenthesized,
-            span_ext: self.span,
+            span_ext: this.lower_span(self.span),
+        };
+        this.arena.alloc(ga)
+    }
+}
+
+fn lifetimes_from_impl_trait_bounds(
+    opaque_ty_id: NodeId,
+    bounds: hir::GenericBounds<'_>,
+    lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
+) -> Vec<(hir::LifetimeName, Span)> {
+    debug!(
+        "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
+             bounds={:#?})",
+        opaque_ty_id, bounds,
+    );
+
+    // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
+    // appear in the bounds, excluding lifetimes that are created within the bounds.
+    // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
+    struct ImplTraitLifetimeCollector<'r> {
+        collect_elided_lifetimes: bool,
+        currently_bound_lifetimes: Vec<hir::LifetimeName>,
+        already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
+        lifetimes: Vec<(hir::LifetimeName, Span)>,
+        lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
+    }
+
+    impl<'r, 'v> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r> {
+        type Map = intravisit::ErasedMap<'v>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::None
+        }
+
+        fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs<'v>) {
+            // Don't collect elided lifetimes used inside of `Fn()` syntax.
+            if parameters.parenthesized {
+                let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                self.collect_elided_lifetimes = false;
+                intravisit::walk_generic_args(self, span, parameters);
+                self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+            } else {
+                intravisit::walk_generic_args(self, span, parameters);
+            }
+        }
+
+        fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
+            // Don't collect elided lifetimes used inside of `fn()` syntax.
+            if let hir::TyKind::BareFn(_) = t.kind {
+                let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
+                self.collect_elided_lifetimes = false;
+
+                // Record the "stack height" of `for<'a>` lifetime bindings
+                // to be able to later fully undo their introduction.
+                let old_len = self.currently_bound_lifetimes.len();
+                intravisit::walk_ty(self, t);
+                self.currently_bound_lifetimes.truncate(old_len);
+
+                self.collect_elided_lifetimes = old_collect_elided_lifetimes;
+            } else {
+                intravisit::walk_ty(self, t)
+            }
+        }
+
+        fn visit_poly_trait_ref(
+            &mut self,
+            trait_ref: &'v hir::PolyTraitRef<'v>,
+            modifier: hir::TraitBoundModifier,
+        ) {
+            // Record the "stack height" of `for<'a>` lifetime bindings
+            // to be able to later fully undo their introduction.
+            let old_len = self.currently_bound_lifetimes.len();
+            intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
+            self.currently_bound_lifetimes.truncate(old_len);
+        }
+
+        fn visit_generic_param(&mut self, param: &'v hir::GenericParam<'v>) {
+            // Record the introduction of 'a in `for<'a> ...`.
+            if let hir::GenericParamKind::Lifetime { .. } = param.kind {
+                // Introduce lifetimes one at a time so that we can handle
+                // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`.
+                let lt_name = hir::LifetimeName::Param(param.name);
+                self.currently_bound_lifetimes.push(lt_name);
+            }
+
+            intravisit::walk_generic_param(self, param);
+        }
+
+        fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
+            let name = match lifetime.name {
+                hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => {
+                    if self.collect_elided_lifetimes {
+                        // Use `'_` for both implicit and underscore lifetimes in
+                        // `type Foo<'_> = impl SomeTrait<'_>;`.
+                        hir::LifetimeName::Underscore
+                    } else {
+                        return;
+                    }
+                }
+                hir::LifetimeName::Param(_) => lifetime.name,
+
+                // Refers to some other lifetime that is "in
+                // scope" within the type.
+                hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
+
+                hir::LifetimeName::Error | hir::LifetimeName::Static => return,
+            };
+
+            if !self.currently_bound_lifetimes.contains(&name)
+                && !self.already_defined_lifetimes.contains(&name)
+                && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
+            {
+                self.already_defined_lifetimes.insert(name);
+
+                self.lifetimes.push((name, lifetime.span));
+            }
         }
     }
+
+    let mut lifetime_collector = ImplTraitLifetimeCollector {
+        collect_elided_lifetimes: true,
+        currently_bound_lifetimes: Vec::new(),
+        already_defined_lifetimes: FxHashSet::default(),
+        lifetimes: Vec::new(),
+        lifetimes_to_include,
+    };
+
+    for bound in bounds {
+        intravisit::walk_param_bound(&mut lifetime_collector, &bound);
+    }
+
+    lifetime_collector.lifetimes
 }
index d81ddd2c082e7af2bc08a3aeb96a7b7f2e458b12..0a9b264aa42636a319b48bca8f2c0a3e2c736c44 100644 (file)
@@ -62,10 +62,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                         let fs = self.arena.alloc_from_iter(fields.iter().map(|f| hir::PatField {
                             hir_id: self.next_id(),
-                            ident: f.ident,
+                            ident: self.lower_ident(f.ident),
                             pat: self.lower_pat(&f.pat),
                             is_shorthand: f.is_shorthand,
-                            span: f.span,
+                            span: self.lower_span(f.span),
                         }));
                         break hir::PatKind::Struct(qpath, fs, etc);
                     }
@@ -247,16 +247,16 @@ fn lower_pat_ident(
                 hir::PatKind::Binding(
                     self.lower_binding_mode(binding_mode),
                     self.lower_node_id(canonical_id),
-                    ident,
+                    self.lower_ident(ident),
                     lower_sub(self),
                 )
             }
             Some(res) => hir::PatKind::Path(hir::QPath::Resolved(
                 None,
                 self.arena.alloc(hir::Path {
-                    span: ident.span,
+                    span: self.lower_span(ident.span),
                     res: self.lower_res(res),
-                    segments: arena_vec![self; hir::PathSegment::from_ident(ident)],
+                    segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))],
                 }),
             )),
         }
@@ -280,7 +280,7 @@ fn pat_with_node_id_of(&mut self, p: &Pat, kind: hir::PatKind<'hir>) -> hir::Pat
         hir::Pat {
             hir_id: self.lower_node_id(p.id),
             kind,
-            span: p.span,
+            span: self.lower_span(p.span),
             default_binding_modes: true,
         }
     }
index 55173c6f8696e419545ef1e8c9a6d8f2157db138..90a22b5c209522864143e6b40c2d20f2fa12af5e 100644 (file)
@@ -90,15 +90,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         _ => ParenthesizedGenericArgs::Err,
                     };
 
-                    let num_lifetimes = type_def_id.map_or(0, |def_id| {
-                        if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
-                            return n;
-                        }
-                        assert!(!def_id.is_local());
-                        let n = self.resolver.item_generics_num_lifetimes(def_id, self.sess);
-                        self.type_def_lifetime_params.insert(def_id, n);
-                        n
-                    });
+                    let num_lifetimes = type_def_id
+                        .map_or(0, |def_id| self.resolver.item_generics_num_lifetimes(def_id));
                     self.lower_path_segment(
                         p.span,
                         segment,
@@ -110,9 +103,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     )
                 },
             )),
-            span: p.segments[..proj_start]
-                .last()
-                .map_or(path_span_lo, |segment| path_span_lo.to(segment.span())),
+            span: self.lower_span(
+                p.segments[..proj_start]
+                    .last()
+                    .map_or(path_span_lo, |segment| path_span_lo.to(segment.span())),
+            ),
         });
 
         // Simple case, either no projections, or only fully-qualified.
@@ -198,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     explicit_owner,
                 )
             })),
-            span: p.span,
+            span: self.lower_span(p.span),
         })
     }
 
@@ -370,14 +365,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         );
 
         hir::PathSegment {
-            ident: segment.ident,
+            ident: self.lower_ident(segment.ident),
             hir_id: Some(id),
             res: Some(self.lower_res(res)),
             infer_args,
             args: if generic_args.is_empty() && generic_args.span.is_empty() {
                 None
             } else {
-                Some(self.arena.alloc(generic_args.into_generic_args(self.arena)))
+                Some(generic_args.into_generic_args(self))
             },
         }
     }
@@ -459,6 +454,12 @@ fn lower_parenthesized_parameter_data(
             parenthesized: false,
             span_ext: DUMMY_SP,
         });
-        hir::TypeBinding { hir_id: self.next_id(), gen_args, span, ident, kind }
+        hir::TypeBinding {
+            hir_id: self.next_id(),
+            gen_args,
+            span: self.lower_span(span),
+            ident,
+            kind,
+        }
     }
 }
index 6b931c598ed8466de1bcb99dc1c26c2518b29da5..4a6eb80fb30ce1ed0bfc0ef92595d9520ba63876 100644 (file)
@@ -14,4 +14,5 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
 rustc_ast = { path = "../rustc_ast" }
index cff1b70dda9073125b637d5e4f73f17c6d8dac58..aca4503903c066e0cd3013401e913ee8a3a45098 100644 (file)
 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::PATTERNS_IN_FNS_WITHOUT_BODY;
+use rustc_session::lint::builtin::{MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY};
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
+use rustc_target::spec::abi;
 use std::mem;
 use std::ops::DerefMut;
 
@@ -33,24 +34,6 @@ enum SelfSemantic {
     No,
 }
 
-/// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
-#[derive(Clone, Copy)]
-enum BoundContext {
-    ImplTrait,
-    TraitBounds,
-    TraitObject,
-}
-
-impl BoundContext {
-    fn description(&self) -> &'static str {
-        match self {
-            Self::ImplTrait => "`impl Trait`",
-            Self::TraitBounds => "supertraits",
-            Self::TraitObject => "trait objects",
-        }
-    }
-}
-
 struct AstValidator<'a> {
     session: &'a Session,
 
@@ -60,6 +43,8 @@ struct AstValidator<'a> {
     /// Are we inside a trait impl?
     in_trait_impl: bool,
 
+    in_const_trait_impl: bool,
+
     has_proc_macro_decls: bool,
 
     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
@@ -67,11 +52,7 @@ struct AstValidator<'a> {
     /// e.g., `impl Iterator<Item = impl Debug>`.
     outer_impl_trait: Option<Span>,
 
-    /// Keeps track of the `BoundContext` as we recurse.
-    ///
-    /// This is used to forbid `?const Trait` bounds in, e.g.,
-    /// `impl Iterator<Item = Box<dyn ?const Trait>`.
-    bound_context: Option<BoundContext>,
+    is_tilde_const_allowed: bool,
 
     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
     /// or `Foo::Bar<impl Trait>`
@@ -88,10 +69,18 @@ struct AstValidator<'a> {
 }
 
 impl<'a> AstValidator<'a> {
-    fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) {
+    fn with_in_trait_impl(
+        &mut self,
+        is_in: bool,
+        constness: Option<Const>,
+        f: impl FnOnce(&mut Self),
+    ) {
         let old = mem::replace(&mut self.in_trait_impl, is_in);
+        let old_const =
+            mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_))));
         f(self);
         self.in_trait_impl = old;
+        self.in_const_trait_impl = old_const;
     }
 
     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
@@ -100,6 +89,18 @@ fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
         self.is_impl_trait_banned = old;
     }
 
+    fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.is_tilde_const_allowed, true);
+        f(self);
+        self.is_tilde_const_allowed = old;
+    }
+
+    fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(&mut self.is_tilde_const_allowed, false);
+        f(self);
+        self.is_tilde_const_allowed = old;
+    }
+
     fn with_let_allowed(&mut self, allowed: bool, f: impl FnOnce(&mut Self, bool)) {
         let old = mem::replace(&mut self.is_let_allowed, allowed);
         f(self, old);
@@ -130,19 +131,13 @@ fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
         let old = mem::replace(&mut self.outer_impl_trait, outer);
         if outer.is_some() {
-            self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
+            self.with_banned_tilde_const(f);
         } else {
-            f(self)
+            f(self);
         }
         self.outer_impl_trait = old;
     }
 
-    fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
-        let old = self.bound_context.replace(ctx);
-        f(self);
-        self.bound_context = old;
-    }
-
     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
         match constraint.kind {
             AssocTyConstraintKind::Equality { .. } => {}
@@ -164,9 +159,7 @@ fn walk_ty(&mut self, t: &'a Ty) {
             TyKind::ImplTrait(..) => {
                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
             }
-            TyKind::TraitObject(..) => {
-                self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
-            }
+            TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
             TyKind::Path(ref qself, ref path) => {
                 // We allow these:
                 //  - `Option<impl Trait>`
@@ -852,6 +845,10 @@ fn visit_ty_common(&mut self, ty: &'a Ty) {
                     .emit();
                 });
                 self.check_late_bound_lifetime_defs(&bfty.generic_params);
+                if let Extern::Implicit = bfty.ext {
+                    let sig_span = self.session.source_map().next_point(ty.span.shrink_to_lo());
+                    self.maybe_lint_missing_abi(sig_span, ty.id);
+                }
             }
             TyKind::TraitObject(ref bounds, ..) => {
                 let mut any_lifetime_bounds = false;
@@ -902,6 +899,26 @@ fn visit_ty_common(&mut self, ty: &'a Ty) {
             _ => {}
         }
     }
+
+    fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId) {
+        // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
+        // call site which do not have a macro backtrace. See #61963.
+        let is_macro_callsite = self
+            .session
+            .source_map()
+            .span_to_snippet(span)
+            .map(|snippet| snippet.starts_with("#["))
+            .unwrap_or(true);
+        if !is_macro_callsite {
+            self.lint_buffer.buffer_lint_with_diagnostic(
+                MISSING_ABI,
+                id,
+                span,
+                "extern declarations without an explicit ABI are deprecated",
+                BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
+            )
+        }
+    }
 }
 
 /// Checks that generic parameters are in the correct order,
@@ -1083,13 +1100,13 @@ fn visit_item(&mut self, item: &'a Item) {
                 unsafety,
                 polarity,
                 defaultness: _,
-                constness: _,
-                generics: _,
+                constness,
+                ref generics,
                 of_trait: Some(ref t),
                 ref self_ty,
-                items: _,
+                ref items,
             }) => {
-                self.with_in_trait_impl(true, |this| {
+                self.with_in_trait_impl(true, Some(constness), |this| {
                     this.invalid_visibility(&item.vis, None);
                     if let TyKind::Err = self_ty.kind {
                         this.err_handler()
@@ -1112,7 +1129,17 @@ fn visit_item(&mut self, item: &'a Item) {
                         .emit();
                     }
 
-                    visit::walk_item(this, item);
+                    this.visit_vis(&item.vis);
+                    this.visit_ident(item.ident);
+                    if let Const::Yes(_) = constness {
+                        this.with_tilde_const_allowed(|this| this.visit_generics(generics));
+                    } else {
+                        this.visit_generics(generics);
+                    }
+                    this.visit_trait_ref(t);
+                    this.visit_ty(self_ty);
+
+                    walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
                 });
                 return; // Avoid visiting again.
             }
@@ -1157,15 +1184,26 @@ fn visit_item(&mut self, item: &'a Item) {
                         .emit();
                 }
             }
-            ItemKind::Fn(box FnKind(def, _, _, ref body)) => {
+            ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => {
                 self.check_defaultness(item.span, def);
 
                 if body.is_none() {
                     let msg = "free function without a body";
                     self.error_item_without_body(item.span, "function", msg, " { <body> }");
                 }
+                self.visit_vis(&item.vis);
+                self.visit_ident(item.ident);
+                if let Const::Yes(_) = sig.header.constness {
+                    self.with_tilde_const_allowed(|this| this.visit_generics(generics));
+                } else {
+                    self.visit_generics(generics);
+                }
+                let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+                self.visit_fn(kind, item.span, item.id);
+                walk_list!(self, visit_attribute, &item.attrs);
+                return; // Avoid visiting again.
             }
-            ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => {
+            ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
                 self.invalid_visibility(
                     &item.vis,
@@ -1174,6 +1212,9 @@ fn visit_item(&mut self, item: &'a Item) {
                 if let Unsafe::Yes(span) = unsafety {
                     self.err_handler().span_err(span, "extern block cannot be declared unsafe");
                 }
+                if abi.is_none() {
+                    self.maybe_lint_missing_abi(item.span, item.id);
+                }
                 visit::walk_item(self, item);
                 self.extern_mod = old_item;
                 return; // Avoid visiting again.
@@ -1206,9 +1247,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
                 self.visit_generics(generics);
-                self.with_bound_context(BoundContext::TraitBounds, |this| {
-                    walk_list!(this, visit_param_bound, bounds);
-                });
+                self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
                 walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
                 walk_list!(self, visit_attribute, &item.attrs);
                 return;
@@ -1281,7 +1320,7 @@ fn visit_item(&mut self, item: &'a Item) {
             _ => {}
         }
 
-        visit::walk_item(self, item)
+        visit::walk_item(self, item);
     }
 
     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
@@ -1340,7 +1379,7 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
     }
 
     fn visit_generics(&mut self, generics: &'a Generics) {
-        let cg_defaults = self.session.features_untracked().const_generics_defaults;
+        let cg_defaults = self.session.features_untracked().unordered_const_ty_params();
 
         let mut prev_param_default = None;
         for param in &generics.params {
@@ -1428,15 +1467,17 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) {
     fn visit_param_bound(&mut self, bound: &'a GenericBound) {
         match bound {
             GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
-                if let Some(ctx) = self.bound_context {
-                    let msg = format!("`?const` is not permitted in {}", ctx.description());
-                    self.err_handler().span_err(bound.span(), &msg);
+                if !self.is_tilde_const_allowed {
+                    self.err_handler()
+                        .struct_span_err(bound.span(), "`~const` is not allowed here")
+                        .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
+                        .emit();
                 }
             }
 
             GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
                 self.err_handler()
-                    .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
+                    .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
             }
 
             _ => {}
@@ -1513,6 +1554,17 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
                 .emit();
         }
 
+        if let FnKind::Fn(
+            _,
+            _,
+            FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. },
+            _,
+            _,
+        ) = fk
+        {
+            self.maybe_lint_missing_abi(*sig_span, id);
+        }
+
         // Functions without bodies cannot have patterns.
         if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
@@ -1589,7 +1641,32 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
             self.check_item_named(item.ident, "const");
         }
 
-        self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
+        match item.kind {
+            AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty))
+                if ctxt == AssocCtxt::Trait =>
+            {
+                self.visit_vis(&item.vis);
+                self.visit_ident(item.ident);
+                walk_list!(self, visit_attribute, &item.attrs);
+                self.with_tilde_const_allowed(|this| {
+                    this.visit_generics(generics);
+                    walk_list!(this, visit_param_bound, bounds);
+                });
+                walk_list!(self, visit_ty, ty);
+            }
+            AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
+                if self.in_const_trait_impl || ctxt == AssocCtxt::Trait =>
+            {
+                self.visit_vis(&item.vis);
+                self.visit_ident(item.ident);
+                self.with_tilde_const_allowed(|this| this.visit_generics(generics));
+                let kind =
+                    FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
+                self.visit_fn(kind, item.span, item.id);
+            }
+            _ => self
+                .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
+        }
     }
 }
 
@@ -1683,9 +1760,10 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
         session,
         extern_mod: None,
         in_trait_impl: false,
+        in_const_trait_impl: false,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
-        bound_context: None,
+        is_tilde_const_allowed: false,
         is_impl_trait_banned: false,
         is_assoc_ty_bound_banned: false,
         is_let_allowed: false,
index 0be26b6f8e9de8d8eb11f86558269f2c87cbaff3..1defb65ed8793d9ef7142dcacee8935f5a95ec43 100644 (file)
@@ -656,7 +656,6 @@ macro_rules! gate_all {
     gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
     gate_all!(generators, "yield syntax is experimental");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
-    gate_all!(const_trait_bound_opt_out, "`?const` on trait bounds is experimental");
     gate_all!(const_trait_impl, "const trait impls are experimental");
     gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
     gate_all!(inline_const, "inline-const is experimental");
@@ -688,7 +687,6 @@ macro_rules! gate_all {
     gate_all!(trait_alias, "trait aliases are experimental");
     gate_all!(associated_type_bounds, "associated type bounds are unstable");
     gate_all!(crate_visibility_modifier, "`crate` visibility modifier is experimental");
-    gate_all!(const_generics, "const generics are unstable");
     gate_all!(decl_macro, "`macro` is experimental");
     gate_all!(box_patterns, "box pattern syntax is experimental");
     gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
index 976725b308e02d6f2631b79db7f29c519acd4e93..e74f38dd89c35c4a34bb572b5c34070bdeb89594 100644 (file)
@@ -8,17 +8,19 @@
 use rustc_ast::token::{Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 
+use std::borrow::Cow;
+
 pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
     State::new().nonterminal_to_string(nt)
 }
 
 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
-pub fn token_kind_to_string(tok: &TokenKind) -> String {
+pub fn token_kind_to_string(tok: &TokenKind) -> Cow<'static, str> {
     State::new().token_kind_to_string(tok)
 }
 
 /// Print the token precisely, without converting `$crate` into its respective crate name.
-pub fn token_to_string(token: &Token) -> String {
+pub fn token_to_string(token: &Token) -> Cow<'static, str> {
     State::new().token_to_string(token)
 }
 
index b09c668273aa8192418b17c4d4537c4403630228..3cf04be160c64a0a8003493187d618cbca4217a2 100644 (file)
@@ -578,6 +578,33 @@ fn print_mac_common(
         }
     }
 
+    fn print_mac_def(
+        &mut self,
+        macro_def: &ast::MacroDef,
+        ident: &Ident,
+        sp: &Span,
+        print_visibility: impl FnOnce(&mut Self),
+    ) {
+        let (kw, has_bang) = if macro_def.macro_rules {
+            ("macro_rules", true)
+        } else {
+            print_visibility(self);
+            ("macro", false)
+        };
+        self.print_mac_common(
+            Some(MacHeader::Keyword(kw)),
+            has_bang,
+            Some(*ident),
+            macro_def.body.delim(),
+            &macro_def.body.inner_tokens(),
+            true,
+            *sp,
+        );
+        if macro_def.body.need_semicolon() {
+            self.word(";");
+        }
+    }
+
     fn print_path(&mut self, path: &ast::Path, colons_before_params: bool, depth: usize) {
         self.maybe_print_comment(path.span.lo());
 
@@ -658,7 +685,7 @@ fn nonterminal_to_string(&self, nt: &Nonterminal) -> String {
     }
 
     /// Print the token kind precisely, without converting `$crate` into its respective crate name.
-    fn token_kind_to_string(&self, tok: &TokenKind) -> String {
+    fn token_kind_to_string(&self, tok: &TokenKind) -> Cow<'static, str> {
         self.token_kind_to_string_ext(tok, None)
     }
 
@@ -666,72 +693,72 @@ fn token_kind_to_string_ext(
         &self,
         tok: &TokenKind,
         convert_dollar_crate: Option<Span>,
-    ) -> String {
+    ) -> Cow<'static, str> {
         match *tok {
-            token::Eq => "=".to_string(),
-            token::Lt => "<".to_string(),
-            token::Le => "<=".to_string(),
-            token::EqEq => "==".to_string(),
-            token::Ne => "!=".to_string(),
-            token::Ge => ">=".to_string(),
-            token::Gt => ">".to_string(),
-            token::Not => "!".to_string(),
-            token::Tilde => "~".to_string(),
-            token::OrOr => "||".to_string(),
-            token::AndAnd => "&&".to_string(),
-            token::BinOp(op) => binop_to_string(op).to_string(),
-            token::BinOpEq(op) => format!("{}=", binop_to_string(op)),
+            token::Eq => "=".into(),
+            token::Lt => "<".into(),
+            token::Le => "<=".into(),
+            token::EqEq => "==".into(),
+            token::Ne => "!=".into(),
+            token::Ge => ">=".into(),
+            token::Gt => ">".into(),
+            token::Not => "!".into(),
+            token::Tilde => "~".into(),
+            token::OrOr => "||".into(),
+            token::AndAnd => "&&".into(),
+            token::BinOp(op) => binop_to_string(op).into(),
+            token::BinOpEq(op) => format!("{}=", binop_to_string(op)).into(),
 
             /* Structural symbols */
-            token::At => "@".to_string(),
-            token::Dot => ".".to_string(),
-            token::DotDot => "..".to_string(),
-            token::DotDotDot => "...".to_string(),
-            token::DotDotEq => "..=".to_string(),
-            token::Comma => ",".to_string(),
-            token::Semi => ";".to_string(),
-            token::Colon => ":".to_string(),
-            token::ModSep => "::".to_string(),
-            token::RArrow => "->".to_string(),
-            token::LArrow => "<-".to_string(),
-            token::FatArrow => "=>".to_string(),
-            token::OpenDelim(token::Paren) => "(".to_string(),
-            token::CloseDelim(token::Paren) => ")".to_string(),
-            token::OpenDelim(token::Bracket) => "[".to_string(),
-            token::CloseDelim(token::Bracket) => "]".to_string(),
-            token::OpenDelim(token::Brace) => "{".to_string(),
-            token::CloseDelim(token::Brace) => "}".to_string(),
-            token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => "".to_string(),
-            token::Pound => "#".to_string(),
-            token::Dollar => "$".to_string(),
-            token::Question => "?".to_string(),
-            token::SingleQuote => "'".to_string(),
+            token::At => "@".into(),
+            token::Dot => ".".into(),
+            token::DotDot => "..".into(),
+            token::DotDotDot => "...".into(),
+            token::DotDotEq => "..=".into(),
+            token::Comma => ",".into(),
+            token::Semi => ";".into(),
+            token::Colon => ":".into(),
+            token::ModSep => "::".into(),
+            token::RArrow => "->".into(),
+            token::LArrow => "<-".into(),
+            token::FatArrow => "=>".into(),
+            token::OpenDelim(token::Paren) => "(".into(),
+            token::CloseDelim(token::Paren) => ")".into(),
+            token::OpenDelim(token::Bracket) => "[".into(),
+            token::CloseDelim(token::Bracket) => "]".into(),
+            token::OpenDelim(token::Brace) => "{".into(),
+            token::CloseDelim(token::Brace) => "}".into(),
+            token::OpenDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => "".into(),
+            token::Pound => "#".into(),
+            token::Dollar => "$".into(),
+            token::Question => "?".into(),
+            token::SingleQuote => "'".into(),
 
             /* Literals */
-            token::Literal(lit) => literal_to_string(lit),
+            token::Literal(lit) => literal_to_string(lit).into(),
 
             /* Name components */
             token::Ident(s, is_raw) => {
-                IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string()
+                IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string().into()
             }
-            token::Lifetime(s) => s.to_string(),
+            token::Lifetime(s) => s.to_string().into(),
 
             /* Other */
             token::DocComment(comment_kind, attr_style, data) => {
-                doc_comment_to_string(comment_kind, attr_style, data)
+                doc_comment_to_string(comment_kind, attr_style, data).into()
             }
-            token::Eof => "<eof>".to_string(),
+            token::Eof => "<eof>".into(),
 
-            token::Interpolated(ref nt) => self.nonterminal_to_string(nt),
+            token::Interpolated(ref nt) => self.nonterminal_to_string(nt).into(),
         }
     }
 
     /// Print the token precisely, without converting `$crate` into its respective crate name.
-    fn token_to_string(&self, token: &Token) -> String {
+    fn token_to_string(&self, token: &Token) -> Cow<'static, str> {
         self.token_to_string_ext(token, false)
     }
 
-    fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> String {
+    fn token_to_string_ext(&self, token: &Token, convert_dollar_crate: bool) -> Cow<'static, str> {
         let convert_dollar_crate = convert_dollar_crate.then_some(token.span);
         self.token_kind_to_string_ext(&token.kind, convert_dollar_crate)
     }
@@ -1305,24 +1332,9 @@ fn print_associated_type(
                 }
             }
             ast::ItemKind::MacroDef(ref macro_def) => {
-                let (kw, has_bang) = if macro_def.macro_rules {
-                    ("macro_rules", true)
-                } else {
-                    self.print_visibility(&item.vis);
-                    ("macro", false)
-                };
-                self.print_mac_common(
-                    Some(MacHeader::Keyword(kw)),
-                    has_bang,
-                    Some(item.ident),
-                    macro_def.body.delim(),
-                    &macro_def.body.inner_tokens(),
-                    true,
-                    item.span,
-                );
-                if macro_def.body.need_semicolon() {
-                    self.word(";");
-                }
+                self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
+                    state.print_visibility(&item.vis)
+                });
             }
         }
         self.ann.post(self, AnnNode::Item(item))
@@ -1506,13 +1518,19 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
                 self.ibox(INDENT_UNIT);
                 self.print_local_decl(loc);
                 self.end();
-                if let Some(ref init) = loc.init {
+                if let Some((init, els)) = loc.kind.init_else_opt() {
                     self.nbsp();
                     self.word_space("=");
                     self.print_expr(init);
+                    if let Some(els) = els {
+                        self.cbox(INDENT_UNIT);
+                        self.ibox(INDENT_UNIT);
+                        self.s.word(" else ");
+                        self.print_block(els);
+                    }
                 }
                 self.s.word(";");
-                self.end();
+                self.end(); // `let` ibox
             }
             ast::StmtKind::Item(ref item) => self.print_item(item),
             ast::StmtKind::Expr(ref expr) => {
index cb0cfdcefdc22b9b8b4f895b7df15203be21e50f..652165fb9b60b1f646c7827aaa07d17548a6e8a1 100644 (file)
@@ -7,10 +7,10 @@
 use rustc_expand::base::{self, *};
 use rustc_parse::parser::Parser;
 use rustc_parse_format as parse;
-use rustc_session::lint::{self, BuiltinLintDiagnostics};
+use rustc_session::lint;
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::{kw, sym, Symbol};
-use rustc_span::{InnerSpan, MultiSpan, Span};
+use rustc_span::{InnerSpan, Span};
 use rustc_target::asm::InlineAsmArch;
 use smallvec::smallvec;
 
@@ -484,11 +484,7 @@ fn parse_reg<'a>(
     Ok(result)
 }
 
-fn expand_preparsed_asm(
-    ecx: &mut ExtCtxt<'_>,
-    args: AsmArgs,
-    is_local_asm: bool,
-) -> Option<ast::InlineAsm> {
+fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::InlineAsm> {
     let mut template = vec![];
     // Register operands are implicitly used since they are not allowed to be
     // referenced in the template string.
@@ -501,6 +497,8 @@ fn expand_preparsed_asm(
     let mut line_spans = Vec::with_capacity(args.templates.len());
     let mut curarg = 0;
 
+    let mut template_strs = Vec::with_capacity(args.templates.len());
+
     for template_expr in args.templates.into_iter() {
         if !template.is_empty() {
             template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
@@ -524,8 +522,13 @@ fn expand_preparsed_asm(
             ast::StrStyle::Raw(raw) => Some(raw as usize),
         };
 
-        let template_str = &template_str.as_str();
         let template_snippet = ecx.source_map().span_to_snippet(template_sp).ok();
+        template_strs.push((
+            template_str,
+            template_snippet.as_ref().map(|s| Symbol::intern(s)),
+            template_sp,
+        ));
+        let template_str = &template_str.as_str();
 
         if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
             let find_span = |needle: &str| -> Span {
@@ -560,72 +563,6 @@ fn expand_preparsed_asm(
             }
         }
 
-        // Lint against the use of named labels in inline `asm!` but not `global_asm!`
-        if is_local_asm {
-            let find_label_span = |needle: &str| -> Option<Span> {
-                if let Some(snippet) = &template_snippet {
-                    if let Some(pos) = snippet.find(needle) {
-                        let end = pos
-                            + &snippet[pos..]
-                                .find(|c| c == ':')
-                                .unwrap_or(snippet[pos..].len() - 1);
-                        let inner = InnerSpan::new(pos, end);
-                        return Some(template_sp.from_inner(inner));
-                    }
-                }
-
-                None
-            };
-
-            let mut found_labels = Vec::new();
-
-            // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
-            let statements = template_str.split(|c| matches!(c, '\n' | ';'));
-            for statement in statements {
-                // If there's a comment, trim it from the statement
-                let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
-                let mut start_idx = 0;
-                for (idx, _) in statement.match_indices(':') {
-                    let possible_label = statement[start_idx..idx].trim();
-                    let mut chars = possible_label.chars();
-                    if let Some(c) = chars.next() {
-                        // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
-                        if (c.is_alphabetic() || matches!(c, '.' | '_'))
-                            && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
-                        {
-                            found_labels.push(possible_label);
-                        } else {
-                            // If we encounter a non-label, there cannot be any further labels, so stop checking
-                            break;
-                        }
-                    } else {
-                        // Empty string means a leading ':' in this section, which is not a label
-                        break;
-                    }
-
-                    start_idx = idx + 1;
-                }
-            }
-
-            if found_labels.len() > 0 {
-                let spans =
-                    found_labels.into_iter().filter_map(find_label_span).collect::<Vec<Span>>();
-                // If there were labels but we couldn't find a span, combine the warnings and use the template span
-                let target_spans: MultiSpan =
-                    if spans.len() > 0 { spans.into() } else { template_sp.into() };
-                ecx.parse_sess().buffer_lint_with_diagnostic(
-                    lint::builtin::NAMED_ASM_LABELS,
-                    target_spans,
-                    ecx.current_expansion.lint_node_id,
-                    "avoid using named labels in inline assembly",
-                    BuiltinLintDiagnostics::NamedAsmLabel(
-                        "only local labels of the form `<number>:` should be used in inline asm"
-                            .to_string(),
-                    ),
-                );
-            }
-        }
-
         // Don't treat raw asm as a format string.
         if args.options.contains(ast::InlineAsmOptions::RAW) {
             template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
@@ -819,6 +756,7 @@ fn expand_preparsed_asm(
 
     Some(ast::InlineAsm {
         template,
+        template_strs: template_strs.into_boxed_slice(),
         operands: args.operands,
         clobber_abi: args.clobber_abi,
         options: args.options,
@@ -833,7 +771,7 @@ pub fn expand_asm<'cx>(
 ) -> Box<dyn base::MacResult + 'cx> {
     match parse_args(ecx, sp, tts, false) {
         Ok(args) => {
-            let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args, true) {
+            let expr = if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 P(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ExprKind::InlineAsm(P(inline_asm)),
@@ -860,7 +798,7 @@ pub fn expand_global_asm<'cx>(
 ) -> Box<dyn base::MacResult + 'cx> {
     match parse_args(ecx, sp, tts, true) {
         Ok(args) => {
-            if let Some(inline_asm) = expand_preparsed_asm(ecx, args, false) {
+            if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 MacEager::items(smallvec![P(ast::Item {
                     ident: Ident::invalid(),
                     attrs: Vec::new(),
index cc6dac52d7663b13619b97b76e21fc9cba25924c..14506f296bf95d294964445da692c648ceceacdc 100644 (file)
@@ -3,7 +3,7 @@
 use crate::deriving::path_std;
 
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, Expr, MetaItem};
+use rustc_ast::{self as ast, Expr, LocalKind, MetaItem};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
@@ -135,8 +135,8 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> as
     let local = P(ast::Local {
         pat: cx.pat_wild(sp),
         ty: None,
-        init: Some(expr),
         id: ast::DUMMY_NODE_ID,
+        kind: LocalKind::Init(expr),
         span: sp,
         attrs: ast::AttrVec::new(),
         tokens: None,
index 572ec6e242e4b4d7fbe1b5410adab8d7a107319a..bcf95719db56b839331c689a787245e5c45409f2 100644 (file)
@@ -102,6 +102,7 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
         span,
         tokens: None,
+        could_be_bare_literal: false,
     }))
 }
 
index 1dbf7728421637343a84b9a9513ccf0cca2b4485..8508b3b7ae6edb9a273d9f05e16950b75096e030 100644 (file)
@@ -867,6 +867,7 @@ fn into_expr(self) -> P<ast::Expr> {
             rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
             span: self.macsp,
             tokens: None,
+            could_be_bare_literal: false,
         }));
 
         let ident = Ident::from_str_and_span("args", self.macsp);
index 7971c1fff428ce7658c3fa64916a72f38495813c..6f61e4cba0776acccf84358c781fa4bd2a4516fa 100644 (file)
@@ -13,7 +13,6 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::smallvec;
-use std::cell::RefCell;
 
 struct ProcMacroDerive {
     id: NodeId,
@@ -90,7 +89,7 @@ pub fn inject(
         return krate;
     }
 
-    let decls = mk_decls(&mut krate, &mut cx, &macros);
+    let decls = mk_decls(&mut cx, &macros);
     krate.items.push(decls);
 
     krate
@@ -289,15 +288,7 @@ fn visit_item(&mut self, item: &'a ast::Item) {
 //              // ...
 //          ];
 //      }
-fn mk_decls(
-    ast_krate: &mut ast::Crate,
-    cx: &mut ExtCtxt<'_>,
-    macros: &[ProcMacro],
-) -> P<ast::Item> {
-    // We're the ones filling in this Vec,
-    // so it should be empty to start with
-    assert!(ast_krate.proc_macros.is_empty());
-
+fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
     let expn_id = cx.resolver.expansion_for_ast_pass(
         DUMMY_SP,
         AstPass::ProcMacroHarness,
@@ -316,26 +307,25 @@ fn mk_decls(
     let attr = Ident::new(sym::attr, span);
     let bang = Ident::new(sym::bang, span);
 
-    let krate_ref = RefCell::new(ast_krate);
-
-    // We add NodeIds to 'krate.proc_macros' in the order
+    // We add NodeIds to 'resolver.proc_macros' in the order
     // that we generate expressions. The position of each NodeId
     // in the 'proc_macros' Vec corresponds to its position
     // in the static array that will be generated
     let decls = {
-        let local_path =
-            |sp: Span, name| cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]));
-        let proc_macro_ty_method_path = |method| {
+        let local_path = |cx: &ExtCtxt<'_>, sp: Span, name| {
+            cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name]))
+        };
+        let proc_macro_ty_method_path = |cx: &ExtCtxt<'_>, method| {
             cx.expr_path(cx.path(span, vec![proc_macro, bridge, client, proc_macro_ty, method]))
         };
         macros
             .iter()
             .map(|m| match m {
                 ProcMacro::Derive(cd) => {
-                    krate_ref.borrow_mut().proc_macros.push(cd.id);
+                    cx.resolver.declare_proc_macro(cd.id);
                     cx.expr_call(
                         span,
-                        proc_macro_ty_method_path(custom_derive),
+                        proc_macro_ty_method_path(cx, custom_derive),
                         vec![
                             cx.expr_str(cd.span, cd.trait_name),
                             cx.expr_vec_slice(
@@ -345,12 +335,12 @@ fn mk_decls(
                                     .map(|&s| cx.expr_str(cd.span, s))
                                     .collect::<Vec<_>>(),
                             ),
-                            local_path(cd.span, cd.function_name),
+                            local_path(cx, cd.span, cd.function_name),
                         ],
                     )
                 }
                 ProcMacro::Def(ca) => {
-                    krate_ref.borrow_mut().proc_macros.push(ca.id);
+                    cx.resolver.declare_proc_macro(ca.id);
                     let ident = match ca.def_type {
                         ProcMacroDefType::Attr => attr,
                         ProcMacroDefType::Bang => bang,
@@ -358,10 +348,10 @@ fn mk_decls(
 
                     cx.expr_call(
                         span,
-                        proc_macro_ty_method_path(ident),
+                        proc_macro_ty_method_path(cx, ident),
                         vec![
                             cx.expr_str(ca.span, ca.function_name.name),
-                            local_path(ca.span, ca.function_name),
+                            local_path(cx, ca.span, ca.function_name),
                         ],
                     )
                 }
index 22897c43e7ef917cdc456010c9129d35aca97c1e..0fa228fc944a160c226f21c2ebec660c1192ba7c 100644 (file)
@@ -4,8 +4,7 @@
 use std::fs::File;
 use std::path::{Path, PathBuf};
 
-use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
-use rustc_codegen_ssa::METADATA_FILENAME;
+use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_session::Session;
 
 use object::{Object, ObjectSymbol, SymbolKind};
@@ -19,7 +18,6 @@ enum ArchiveEntry {
 pub(crate) struct ArArchiveBuilder<'a> {
     sess: &'a Session,
     dst: PathBuf,
-    lib_search_paths: Vec<PathBuf>,
     use_gnu_style_archive: bool,
     no_builtin_ranlib: bool,
 
@@ -31,8 +29,6 @@ pub(crate) struct ArArchiveBuilder<'a> {
 
 impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
     fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
-        use rustc_codegen_ssa::back::link::archive_search_paths;
-
         let (src_archives, entries) = if let Some(input) = input {
             let mut archive = ar::Archive::new(File::open(input).unwrap());
             let mut entries = Vec::new();
@@ -55,7 +51,6 @@ fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
         ArArchiveBuilder {
             sess,
             dst: output.to_path_buf(),
-            lib_search_paths: archive_search_paths(sess),
             use_gnu_style_archive: sess.target.archive_format == "gnu",
             // FIXME fix builtin ranlib on macOS
             no_builtin_ranlib: sess.target.is_like_osx,
@@ -85,42 +80,27 @@ fn add_file(&mut self, file: &Path) {
         ));
     }
 
-    fn add_native_library(&mut self, name: rustc_span::symbol::Symbol, verbatim: bool) {
-        let location = find_library(name, verbatim, &self.lib_search_paths, self.sess);
-        self.add_archive(location.clone(), |_| false).unwrap_or_else(|e| {
-            panic!("failed to add native library {}: {}", location.to_string_lossy(), e);
-        });
-    }
-
-    fn add_rlib(
-        &mut self,
-        rlib: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> std::io::Result<()> {
-        let obj_start = name.to_owned();
-
-        self.add_archive(rlib.to_owned(), move |fname: &str| {
-            // Ignore metadata files, no matter the name.
-            if fname == METADATA_FILENAME {
-                return true;
-            }
-
-            // Don't include Rust objects if LTO is enabled
-            if lto && fname.starts_with(&obj_start) && fname.ends_with(".o") {
-                return true;
-            }
+    fn add_archive<F>(&mut self, archive_path: &Path, mut skip: F) -> std::io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static,
+    {
+        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
+        let archive_index = self.src_archives.len();
 
-            // Otherwise if this is *not* a rust object and we're skipping
-            // objects then skip this file
-            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                return true;
+        let mut i = 0;
+        while let Some(entry) = archive.next_entry() {
+            let entry = entry?;
+            let file_name = String::from_utf8(entry.header().identifier().to_vec())
+                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
+            if !skip(&file_name) {
+                self.entries
+                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
             }
+            i += 1;
+        }
 
-            // ok, don't skip this
-            false
-        })
+        self.src_archives.push((archive_path.to_owned(), archive));
+        Ok(())
     }
 
     fn update_symbols(&mut self) {}
@@ -264,28 +244,3 @@ fn inject_dll_import_lib(
         bug!("injecting dll imports is not supported");
     }
 }
-
-impl<'a> ArArchiveBuilder<'a> {
-    fn add_archive<F>(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
-        let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
-        let archive_index = self.src_archives.len();
-
-        let mut i = 0;
-        while let Some(entry) = archive.next_entry() {
-            let entry = entry?;
-            let file_name = String::from_utf8(entry.header().identifier().to_vec())
-                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
-            if !skip(&file_name) {
-                self.entries
-                    .push((file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }));
-            }
-            i += 1;
-        }
-
-        self.src_archives.push((archive_path, archive));
-        Ok(())
-    }
-}
index 892ccf27f6df893f713a62e9cf387f951848da98..6f7ca51d038c0155233e9ad8dcea64cfa70a6b47 100644 (file)
@@ -1,4 +1,5 @@
 use rustc_index::vec::IndexVec;
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers};
 use rustc_middle::ty::SymbolName;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
@@ -256,12 +257,12 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) inline_asm_index: u32,
 }
 
-impl<'tcx> LayoutOf for FunctionCx<'_, '_, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
-        RevealAllLayoutCx(self.tcx).layout_of(ty)
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
     }
 }
 
@@ -364,19 +365,16 @@ pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
 
 pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
 
-impl<'tcx> LayoutOf for RevealAllLayoutCx<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
-        assert!(!ty.still_further_specializable());
-        self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| {
-            if let layout::LayoutError::SizeOverflow(_) = e {
-                self.0.sess.fatal(&e.to_string())
-            } else {
-                bug!("failed to get layout for `{}`: {}", ty, e)
-            }
-        })
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        if let layout::LayoutError::SizeOverflow(_) = err {
+            self.0.sess.span_fatal(span, &err.to_string())
+        } else {
+            span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+        }
     }
 }
 
index c87309e22224f8955a17c639b646e7e782fecea4..424a0d742d12b56c29b4b40339faedb7d6b204dd 100644 (file)
@@ -129,13 +129,13 @@ pub(crate) fn codegen_constant<'tcx>(
     };
     let const_val = match const_.val {
         ConstKind::Value(const_val) => const_val,
-        ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
-            if fx.tcx.is_static(def.did) =>
+        ConstKind::Unevaluated(uv)
+            if fx.tcx.is_static(uv.def.did) =>
         {
-            assert!(substs.is_empty());
-            assert!(promoted.is_none());
+            assert!(uv.substs(fx.tcx).is_empty());
+            assert!(uv.promoted.is_none());
 
-            return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
+            return codegen_static_ref(fx, uv.def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
         }
         ConstKind::Unevaluated(unevaluated) => {
             match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
index c471da83de2342f0151328f78206457d1252b771..cabe3e43b342c5bc8f9e20bb336fb0bb9fdc2c50 100644 (file)
@@ -66,7 +66,7 @@ pub(crate) fn new(tcx: TyCtxt<'tcx>, isa: &dyn TargetIsa) -> Self {
             rustc_interface::util::version_str().unwrap_or("unknown version"),
             cranelift_codegen::VERSION,
         );
-        let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(false).into_owned();
+        let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped).into_owned();
         let (name, file_info) = match tcx.sess.local_crate_source_file.clone() {
             Some(path) => {
                 let name = path.to_string_lossy().into_owned();
@@ -160,12 +160,10 @@ fn dwarf_ty(&mut self, ty: Ty<'tcx>) -> UnitEntryId {
 
                 for (field_idx, field_def) in variant.fields.iter().enumerate() {
                     let field_offset = layout.fields.offset(field_idx);
-                    let field_layout = layout
-                        .field(
-                            &layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() },
-                            field_idx,
-                        )
-                        .unwrap();
+                    let field_layout = layout.field(
+                        &layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() },
+                        field_idx,
+                    );
 
                     let field_type = self.dwarf_ty(field_layout.ty);
 
index a8b802f449437622770ff9426fd524ac4273c1f2..3de706ed6d7afdb547d7171819dbc0a2a711b453 100644 (file)
@@ -68,14 +68,13 @@ fn reuse_workproduct_for_cgu(
     cgu: &CodegenUnit<'_>,
     work_products: &mut FxHashMap<WorkProductId, WorkProduct>,
 ) -> CompiledModule {
-    let incr_comp_session_dir = tcx.sess.incr_comp_session_dir();
     let mut object = None;
     let work_product = cgu.work_product(tcx);
     if let Some(saved_file) = &work_product.saved_file {
         let obj_out =
             tcx.output_filenames(()).temp_path(OutputType::Object, Some(&cgu.name().as_str()));
         object = Some(obj_out.clone());
-        let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
+        let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &saved_file);
         if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
             tcx.sess.err(&format!(
                 "unable to copy {} to {}: {}",
index 1c4d307fc50e14c4281b5bd487b83137e7342a33..12f61e0c564aab39944b735e7d4f34057a8df842 100644 (file)
@@ -789,7 +789,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 return;
             }
 
-            if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true).unwrap() {
+            if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true) {
                 with_no_trimmed_paths(|| crate::base::codegen_panic(
                     fx,
                     &format!("attempted to zero-initialize type `{}`, which is invalid", T),
@@ -798,7 +798,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
                 return;
             }
 
-            if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false).unwrap() {
+            if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false) {
                 with_no_trimmed_paths(|| crate::base::codegen_panic(
                     fx,
                     &format!("attempted to leave type `{}` uninitialized, which is invalid", T),
index 4ef53663ca0d95219549c88c440ecf9a0b50522a..2e5e8f683cdaaad47aa2e75c1ef4775345a9ba10 100644 (file)
 mod prelude {
     pub(crate) use std::convert::{TryFrom, TryInto};
 
-    pub(crate) use rustc_span::Span;
+    pub(crate) use rustc_span::{Span, FileNameDisplayPreference};
 
     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
     pub(crate) use rustc_middle::bug;
     pub(crate) use rustc_middle::mir::{self, *};
-    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
+    pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
     pub(crate) use rustc_middle::ty::{
         self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
         TypeFoldable, UintTy,
     };
-    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
+    pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};
 
     pub(crate) use rustc_data_structures::fx::FxHashMap;
 
index 6187f4000fbd224956c1413cff3cf68a65bbd0fe..521ce344180a1063fdbee45863a2c64df17b07d3 100644 (file)
@@ -15,7 +15,7 @@ measureme = "9.1.0"
 snap = "1"
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
-rustc-demangle = "0.1.18"
+rustc-demangle = "0.1.21"
 rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
index abf0ea8cc0a65b05c4329b1312e507a17eb2a698..cd55a61cbaf9d7b4c7675d73ff985a4478cf9fcf 100644 (file)
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::MemFlags;
 use rustc_middle::bug;
+use rustc_middle::ty::layout::LayoutOf;
 pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc_middle::ty::Ty;
 use rustc_target::abi::call::ArgAbi;
 pub use rustc_target::abi::call::*;
-use rustc_target::abi::{self, HasDataLayout, Int, LayoutOf};
+use rustc_target::abi::{self, HasDataLayout, Int};
 pub use rustc_target::spec::abi::Abi;
 
 use libc::c_uint;
index 2d79b73cf9f519e921d2c50626c5228b093ae700..30d91b41a8e8b2b8a02b750a2b38c149cff4b3c3 100644 (file)
@@ -3,19 +3,22 @@
 use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::DebugInfo;
 use rustc_span::symbol::sym;
 
+use crate::debuginfo;
 use crate::llvm::{self, False, True};
 use crate::ModuleLlvm;
 
 pub(crate) unsafe fn codegen(
     tcx: TyCtxt<'_>,
-    mods: &mut ModuleLlvm,
+    module_llvm: &mut ModuleLlvm,
+    module_name: &str,
     kind: AllocatorKind,
     has_alloc_error_handler: bool,
 ) {
-    let llcx = &*mods.llcx;
-    let llmod = mods.llmod();
+    let llcx = &*module_llvm.llcx;
+    let llmod = module_llvm.llmod();
     let usize = match tcx.sess.target.pointer_width {
         16 => llvm::LLVMInt16TypeInContext(llcx),
         32 => llvm::LLVMInt32TypeInContext(llcx),
@@ -132,4 +135,10 @@ pub(crate) unsafe fn codegen(
     llvm::LLVMSetTailCall(ret, True);
     llvm::LLVMBuildRetVoid(llbuilder);
     llvm::LLVMDisposeBuilder(llbuilder);
+
+    if tcx.sess.opts.debuginfo != DebugInfo::None {
+        let dbg_cx = debuginfo::CrateDebugContext::new(llmod);
+        debuginfo::metadata::compile_unit_metadata(tcx, module_name, &dbg_cx);
+        dbg_cx.finalize(tcx.sess);
+    }
 }
index 4387f5301a58d0a4aec1ef6d0704d078b1b17f38..e0d312727a57df3b48807229b5d66030238e9a37 100644 (file)
@@ -314,6 +314,7 @@ fn codegen_inline_asm(
                 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
                 InlineAsmArch::Hexagon => {}
                 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
+                InlineAsmArch::S390x => {}
                 InlineAsmArch::SpirV => {}
                 InlineAsmArch::Wasm32 => {}
                 InlineAsmArch::Bpf => {}
@@ -615,6 +616,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
+            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
+            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+                unreachable!("clobber-only")
+            }
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
@@ -633,6 +638,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
+            InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
                 bug!("LLVM backend does not support SPIR-V")
             }
@@ -711,6 +718,7 @@ fn modifier_to_llvm(
         }
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
         InlineAsmRegClass::Bpf(_) => None,
+        InlineAsmRegClass::S390x(_) => None,
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
@@ -751,6 +759,10 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
+        InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
+        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+            unreachable!("clobber-only")
+        }
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
@@ -769,6 +781,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
         InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
         InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
+        InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
+        InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
index 6ac7093b7dee833870d4568529293b088950f62f..4e86946219fb151676c38889abe6a7b560ec0ad3 100644 (file)
@@ -9,18 +9,15 @@
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
 use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
-use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
-use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
+use rustc_codegen_ssa::back::archive::ArchiveBuilder;
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_middle::middle::cstore::{DllCallingConvention, DllImport};
 use rustc_session::Session;
-use rustc_span::symbol::Symbol;
 
 struct ArchiveConfig<'a> {
     pub sess: &'a Session,
     pub dst: PathBuf,
     pub src: Option<PathBuf>,
-    pub lib_search_paths: Vec<PathBuf>,
 }
 
 /// Helper for adding many files to an archive.
@@ -54,13 +51,7 @@ fn is_relevant_child(c: &Child<'_>) -> bool {
 }
 
 fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> {
-    use rustc_codegen_ssa::back::link::archive_search_paths;
-    ArchiveConfig {
-        sess,
-        dst: output.to_path_buf(),
-        src: input.map(|p| p.to_path_buf()),
-        lib_search_paths: archive_search_paths(sess),
-    }
+    ArchiveConfig { sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()) }
 }
 
 /// Map machine type strings to values of LLVM's MachineTypes enum.
@@ -111,57 +102,23 @@ fn src_files(&mut self) -> Vec<String> {
             .collect()
     }
 
-    /// Adds all of the contents of a native library to this archive. This will
-    /// search in the relevant locations for a library named `name`.
-    fn add_native_library(&mut self, name: Symbol, verbatim: bool) {
-        let location =
-            find_library(name, verbatim, &self.config.lib_search_paths, self.config.sess);
-        self.add_archive(&location, |_| false).unwrap_or_else(|e| {
-            self.config.sess.fatal(&format!(
-                "failed to add native library {}: {}",
-                location.to_string_lossy(),
-                e
-            ));
+    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static,
+    {
+        let archive_ro = match ArchiveRO::open(archive) {
+            Ok(ar) => ar,
+            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
+        };
+        if self.additions.iter().any(|ar| ar.path() == archive) {
+            return Ok(());
+        }
+        self.additions.push(Addition::Archive {
+            path: archive.to_path_buf(),
+            archive: archive_ro,
+            skip: Box::new(skip),
         });
-    }
-
-    /// Adds all of the contents of the rlib at the specified path to this
-    /// archive.
-    ///
-    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
-    /// then the object file also isn't added.
-    fn add_rlib(
-        &mut self,
-        rlib: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> io::Result<()> {
-        // Ignoring obj file starting with the crate name
-        // as simple comparison is not enough - there
-        // might be also an extra name suffix
-        let obj_start = name.to_owned();
-
-        self.add_archive(rlib, move |fname: &str| {
-            // Ignore metadata files, no matter the name.
-            if fname == METADATA_FILENAME {
-                return true;
-            }
-
-            // Don't include Rust objects if LTO is enabled
-            if lto && looks_like_rust_object_file(fname) {
-                return true;
-            }
-
-            // Otherwise if this is *not* a rust object and we're skipping
-            // objects then skip this file
-            if skip_objects && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
-                return true;
-            }
-
-            // ok, don't skip this
-            false
-        })
+        Ok(())
     }
 
     /// Adds an arbitrary file to this archive
@@ -270,25 +227,6 @@ fn src_archive(&mut self) -> Option<&ArchiveRO> {
         self.src_archive.as_ref().unwrap().as_ref()
     }
 
-    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
-    where
-        F: FnMut(&str) -> bool + 'static,
-    {
-        let archive_ro = match ArchiveRO::open(archive) {
-            Ok(ar) => ar,
-            Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
-        };
-        if self.additions.iter().any(|ar| ar.path() == archive) {
-            return Ok(());
-        }
-        self.additions.push(Addition::Archive {
-            path: archive.to_path_buf(),
-            archive: archive_ro,
-            skip: Box::new(skip),
-        });
-        Ok(())
-    }
-
     fn llvm_archive_kind(&self) -> Result<ArchiveKind, &str> {
         let kind = &*self.config.sess.target.archive_format;
         kind.parse().map_err(|_| kind)
index 07e1b55afe5be961bf73d46dd2939367bac9bddc..da24fe08f0dfd6b7349e5290c27b216671de7678 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 use rustc_target::abi::{self, Align, Size};
@@ -88,12 +88,12 @@ fn target_spec(&self) -> &Target {
     }
 }
 
-impl abi::LayoutOf for Builder<'_, '_, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.cx.layout_of(ty)
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        self.cx.handle_layout_err(err, span, ty)
     }
 }
 
@@ -462,7 +462,6 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
             load: &'ll Value,
             scalar: &abi::Scalar,
         ) {
-            let vr = scalar.valid_range.clone();
             match scalar.value {
                 abi::Int(..) => {
                     let range = scalar.valid_range_exclusive(bx);
@@ -470,7 +469,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
                         bx.range_metadata(load, range);
                     }
                 }
-                abi::Pointer if vr.start() < vr.end() && !vr.contains(&0) => {
+                abi::Pointer if !scalar.valid_range.contains_zero() => {
                     bx.nonnull_metadata(load);
                 }
                 _ => {}
index 5532f53e40823fc0ede2a3e56ed85206001637e7..cee582aec95ebf077b818093c990d77044451c07 100644 (file)
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar};
-use rustc_middle::ty::{layout::TyAndLayout, ScalarInt};
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::ScalarInt;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{self, AddressSpace, HasDataLayout, LayoutOf, Pointer, Size};
+use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer, Size};
 
 use libc::{c_char, c_uint};
 use tracing::debug;
index e1baf95e1d9e5c0325f9addcc3abf471b579aeaf..e673b06f1552795b6b65ec64abf335a9ba20ded7 100644 (file)
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::interpret::{
-    read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, Scalar as InterpScalar,
+    read_target_uint, Allocation, ErrorHandled, GlobalAlloc, InitChunk, Pointer,
+    Scalar as InterpScalar,
 };
 use rustc_middle::mir::mono::MonoItem;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
-use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
+use rustc_target::abi::{
+    AddressSpace, Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
+};
+use std::ops::Range;
 use tracing::debug;
 
 pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
@@ -24,6 +29,57 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
     let dl = cx.data_layout();
     let pointer_size = dl.pointer_size.bytes() as usize;
 
+    // Note: this function may call `inspect_with_uninit_and_ptr_outside_interpreter`,
+    // so `range` must be within the bounds of `alloc` and not contain or overlap a relocation.
+    fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
+        llvals: &mut Vec<&'ll Value>,
+        cx: &'a CodegenCx<'ll, 'b>,
+        alloc: &'a Allocation,
+        range: Range<usize>,
+    ) {
+        let mut chunks = alloc
+            .init_mask()
+            .range_as_init_chunks(Size::from_bytes(range.start), Size::from_bytes(range.end));
+
+        let chunk_to_llval = move |chunk| match chunk {
+            InitChunk::Init(range) => {
+                let range = (range.start.bytes() as usize)..(range.end.bytes() as usize);
+                let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
+                cx.const_bytes(bytes)
+            }
+            InitChunk::Uninit(range) => {
+                let len = range.end.bytes() - range.start.bytes();
+                cx.const_undef(cx.type_array(cx.type_i8(), len))
+            }
+        };
+
+        // Generating partially-uninit consts inhibits optimizations, so it is disabled by default.
+        // See https://github.com/rust-lang/rust/issues/84565.
+        let allow_partially_uninit =
+            match cx.sess().opts.debugging_opts.partially_uninit_const_threshold {
+                Some(max) => range.len() <= max,
+                None => false,
+            };
+
+        if allow_partially_uninit {
+            llvals.extend(chunks.map(chunk_to_llval));
+        } else {
+            let llval = match (chunks.next(), chunks.next()) {
+                (Some(chunk), None) => {
+                    // exactly one chunk, either fully init or fully uninit
+                    chunk_to_llval(chunk)
+                }
+                _ => {
+                    // partially uninit, codegen as if it was initialized
+                    // (using some arbitrary value for uninit bytes)
+                    let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
+                    cx.const_bytes(bytes)
+                }
+            };
+            llvals.push(llval);
+        }
+    }
+
     let mut next_offset = 0;
     for &(offset, alloc_id) in alloc.relocations().iter() {
         let offset = offset.bytes();
@@ -32,12 +88,8 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         if offset > next_offset {
             // This `inspect` is okay since we have checked that it is not within a relocation, it
             // is within the bounds of the allocation, and it doesn't affect interpreter execution
-            // (we inspect the result after interpreter execution). Any undef byte is replaced with
-            // some arbitrary byte value.
-            //
-            // FIXME: relay undef bytes to codegen as undef const bytes
-            let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset);
-            llvals.push(cx.const_bytes(bytes));
+            // (we inspect the result after interpreter execution).
+            append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, next_offset..offset);
         }
         let ptr_offset = read_target_uint(
             dl.endian,
@@ -59,7 +111,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
                 Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
                 &cx.tcx,
             ),
-            &Scalar { value: Primitive::Pointer, valid_range: 0..=!0 },
+            &Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
             cx.type_i8p_ext(address_space),
         ));
         next_offset = offset + pointer_size;
@@ -68,12 +120,8 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
         let range = next_offset..alloc.len();
         // This `inspect` is okay since we have check that it is after all relocations, it is
         // within the bounds of the allocation, and it doesn't affect interpreter execution (we
-        // inspect the result after interpreter execution). Any undef byte is replaced with some
-        // arbitrary byte value.
-        //
-        // FIXME: relay undef bytes to codegen as undef const bytes
-        let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
-        llvals.push(cx.const_bytes(bytes));
+        // inspect the result after interpreter execution).
+        append_chunks_of_init_and_uninit_bytes(&mut llvals, cx, alloc, range);
     }
 
     cx.const_struct(&llvals, true)
index 35c866d48a41b489ca4a2ce200ecbce082041914..2d397dc58353402fe76e6b4925e376176376a071 100644 (file)
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_middle::bug;
 use rustc_middle::mir::mono::CodegenUnit;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CFGuard, CrateType, DebugInfo};
 use rustc_session::Session;
-use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{HasDataLayout, LayoutOf, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
 use smallvec::SmallVec;
 
@@ -835,22 +835,16 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
-impl LayoutOf for CodegenCx<'ll, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.spanned_layout_of(ty, DUMMY_SP)
-    }
-
-    fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::TyAndLayout {
-        self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap_or_else(|e| {
-            if let LayoutError::SizeOverflow(_) = e {
-                self.sess().span_fatal(span, &e.to_string())
-            } else {
-                bug!("failed to get layout for `{}`: {}", ty, e)
-            }
-        })
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        if let LayoutError::SizeOverflow(_) = err {
+            self.sess().span_fatal(span, &err.to_string())
+        } else {
+            span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+        }
     }
 }
 
index 8ff2f1cc6520f0b41872fd53160eeb480aa4a571..9a6391443dd010a2c383ceaf3479eb477c02ad8b 100644 (file)
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::ich::NodeIdHashingMode;
 use rustc_middle::mir::{self, GeneratorLayout};
-use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::{Interner, Symbol};
+use rustc_span::FileNameDisplayPreference;
 use rustc_span::{self, SourceFile, SourceFileHash, Span};
-use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
+use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
 use tracing::debug;
@@ -771,7 +772,13 @@ pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll
     let hash = Some(&source_file.src_hash);
     let file_name = Some(source_file.name.prefer_remapped().to_string());
     let directory = if source_file.is_real_file() && !source_file.is_imported() {
-        Some(cx.sess().opts.working_dir.to_string_lossy(false).to_string())
+        Some(
+            cx.sess()
+                .opts
+                .working_dir
+                .to_string_lossy(FileNameDisplayPreference::Remapped)
+                .to_string(),
+        )
     } else {
         // If the path comes from an upstream crate we assume it has been made
         // independent of the compiler's working directory one way or another.
@@ -999,7 +1006,7 @@ pub fn compile_unit_metadata(
     let producer = format!("clang LLVM ({})", rustc_producer);
 
     let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
-    let work_dir = tcx.sess.opts.working_dir.to_string_lossy(false);
+    let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped);
     let flags = "\0";
     let output_filenames = tcx.output_filenames(());
     let out_dir = &output_filenames.out_directory;
index 8375d4c7ca561223b1c561cfd7157a4d3f95e1c7..fbaf8c8bdf63ddf33468227d37532995c0e05e55 100644 (file)
 use rustc_hir::def_id::{DefId, DefIdMap};
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
 use rustc_session::config::{self, DebugInfo};
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span};
-use rustc_target::abi::{LayoutOf, Primitive, Size};
+use rustc_target::abi::{Primitive, Size};
 
 use libc::c_uint;
 use smallvec::SmallVec;
@@ -95,45 +96,52 @@ pub fn new(llmod: &'a llvm::Module) -> Self {
             composite_types_completed: Default::default(),
         }
     }
-}
-
-/// Creates any deferred debug metadata nodes
-pub fn finalize(cx: &CodegenCx<'_, '_>) {
-    if cx.dbg_cx.is_none() {
-        return;
-    }
 
-    debug!("finalize");
+    pub fn finalize(&self, sess: &Session) {
+        unsafe {
+            llvm::LLVMRustDIBuilderFinalize(self.builder);
+
+            // Debuginfo generation in LLVM by default uses a higher
+            // version of dwarf than macOS currently understands. We can
+            // instruct LLVM to emit an older version of dwarf, however,
+            // for macOS to understand. For more info see #11352
+            // This can be overridden using --llvm-opts -dwarf-version,N.
+            // Android has the same issue (#22398)
+            if let Some(version) = sess.target.dwarf_version {
+                llvm::LLVMRustAddModuleFlag(self.llmod, "Dwarf Version\0".as_ptr().cast(), version)
+            }
 
-    if gdb::needs_gdb_debug_scripts_section(cx) {
-        // Add a .debug_gdb_scripts section to this compile-unit. This will
-        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
-        // which activates the Rust pretty printers for binary this section is
-        // contained in.
-        gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
-    }
+            // Indicate that we want CodeView debug information on MSVC
+            if sess.target.is_like_msvc {
+                llvm::LLVMRustAddModuleFlag(self.llmod, "CodeView\0".as_ptr().cast(), 1)
+            }
 
-    unsafe {
-        llvm::LLVMRustDIBuilderFinalize(DIB(cx));
-        // Debuginfo generation in LLVM by default uses a higher
-        // version of dwarf than macOS currently understands. We can
-        // instruct LLVM to emit an older version of dwarf, however,
-        // for macOS to understand. For more info see #11352
-        // This can be overridden using --llvm-opts -dwarf-version,N.
-        // Android has the same issue (#22398)
-        if let Some(version) = cx.sess().target.dwarf_version {
-            llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), version)
+            // Prevent bitcode readers from deleting the debug info.
+            let ptr = "Debug Info Version\0".as_ptr();
+            llvm::LLVMRustAddModuleFlag(
+                self.llmod,
+                ptr.cast(),
+                llvm::LLVMRustDebugMetadataVersion(),
+            );
         }
+    }
+}
 
-        // Indicate that we want CodeView debug information on MSVC
-        if cx.sess().target.is_like_msvc {
-            llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1)
+/// Creates any deferred debug metadata nodes
+pub fn finalize(cx: &CodegenCx<'_, '_>) {
+    if let Some(dbg_cx) = &cx.dbg_cx {
+        debug!("finalize");
+
+        if gdb::needs_gdb_debug_scripts_section(cx) {
+            // Add a .debug_gdb_scripts section to this compile-unit. This will
+            // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
+            // which activates the Rust pretty printers for binary this section is
+            // contained in.
+            gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
         }
 
-        // Prevent bitcode readers from deleting the debug info.
-        let ptr = "Debug Info Version\0".as_ptr();
-        llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion());
-    };
+        dbg_cx.finalize(cx.sess());
+    }
 }
 
 impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
@@ -499,7 +507,7 @@ fn get_containing_scope<'ll, 'tcx>(
                         ty::Adt(def, ..) if !def.is_box() => {
                             // Again, only create type information if full debuginfo is enabled
                             if cx.sess().opts.debuginfo == DebugInfo::Full
-                                && !impl_self_ty.needs_subst()
+                                && !impl_self_ty.definitely_needs_subst(cx.tcx)
                             {
                                 Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
                             } else {
index e30c49295ba8c2b7054d5812651cc0a99ffb87ad..1aa52d975e9a015854dedef358b1c9e67955661f 100644 (file)
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
-use rustc_target::abi::{self, HasDataLayout, LayoutOf, Primitive};
+use rustc_target::abi::{self, HasDataLayout, Primitive};
 use rustc_target::spec::PanicStrategy;
 
 use std::cmp::Ordering;
index 1e6e5252b25ded1b2045b0b21175e9280a61c1b4..1da14344b1d26616a6f8f4a2f7d42ef28824cfe9 100644 (file)
@@ -92,11 +92,12 @@ fn write_compressed_metadata<'tcx>(
     fn codegen_allocator<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
-        mods: &mut ModuleLlvm,
+        module_llvm: &mut ModuleLlvm,
+        module_name: &str,
         kind: AllocatorKind,
         has_alloc_error_handler: bool,
     ) {
-        unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) }
+        unsafe { allocator::codegen(tcx, module_llvm, module_name, kind, has_alloc_error_handler) }
     }
     fn compile_codegen_unit(
         &self,
index 0ca51bd288317feee81b98ddf561e64b88c3b9cd..3b64ec1a99122c389952e810f7c6a3f0bdf9f219 100644 (file)
@@ -89,13 +89,14 @@ fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
             add("-generate-arange-section", false);
         }
 
-        // FIXME(nagisa): disable the machine outliner by default in LLVM versions 11, where it was
-        // introduced and up.
+        // Disable the machine outliner by default in LLVM versions 11 and LLVM
+        // version 12, where it leads to miscompilation.
         //
-        // This should remain in place until https://reviews.llvm.org/D103167 is fixed. If LLVM
-        // has been upgraded since, consider adjusting the version check below to contain an upper
-        // bound.
-        if llvm_util::get_version() >= (11, 0, 0) {
+        // Ref:
+        // - https://github.com/rust-lang/rust/issues/85351
+        // - https://reviews.llvm.org/D103167
+        let llvm_version = llvm_util::get_version();
+        if llvm_version >= (11, 0, 0) && llvm_version < (13, 0, 0) {
             add("-enable-machine-outliner=never", false);
         }
 
index 8a8ece640fcc71ccc2d05d7738013191c09fa46f..8ba3e870fbb71ca231968d12fbae82e27c91ff68 100644 (file)
@@ -8,10 +8,9 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 pub use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
 use rustc_session::config::CrateType;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::RelocModel;
 use tracing::debug;
 
index 85efe3e64836c76c5df392129d6095f1f8b45c7f..d615d230ea0d19a45dc5fca07233cc39cbb67526 100644 (file)
@@ -4,12 +4,12 @@
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F32, F64};
-use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAndLayoutMethods, Variants};
+use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
 use smallvec::{smallvec, SmallVec};
 use tracing::debug;
 
@@ -393,12 +393,15 @@ fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 {
         }
     }
 
+    // FIXME(eddyb) this having the same name as `TyAndLayout::pointee_info_at`
+    // (the inherent method, which is lacking this caching logic) can result in
+    // the uncached version being called - not wrong, but potentially inefficient.
     fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo> {
         if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
             return pointee;
         }
 
-        let result = Ty::pointee_info_at(*self, cx, offset);
+        let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset);
 
         cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
         result
index 2208ec37a423551539391ea47ba4ab10e883e2d2..caafae6c26750aaa9a7114bbe1fab3f65095f63e 100644 (file)
@@ -7,9 +7,9 @@
     common::IntPredicate,
     traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
 };
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, Endian, HasDataLayout, Size};
 
 fn round_pointer_up_to_alignment(
     bx: &mut Builder<'a, 'll, 'tcx>,
index 930b4dc4d415380382748370defe2b48e664b523..1446624b8815743269f2124ff20e6ce4ebf8b125 100644 (file)
@@ -36,6 +36,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 
 [dependencies.object]
-version = "0.26.1"
+version = "0.26.2"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
index 63f457bb979e3ff693f0702c228ca693545a9553..5188abdbe628632e8be71bd203ee52bf2141513c 100644 (file)
@@ -6,7 +6,7 @@
 use std::io;
 use std::path::{Path, PathBuf};
 
-pub fn find_library(
+pub(super) fn find_library(
     name: Symbol,
     verbatim: bool,
     search_paths: &[PathBuf],
@@ -48,14 +48,9 @@ pub trait ArchiveBuilder<'a> {
     fn remove_file(&mut self, name: &str);
     fn src_files(&mut self) -> Vec<String>;
 
-    fn add_rlib(
-        &mut self,
-        path: &Path,
-        name: &str,
-        lto: bool,
-        skip_objects: bool,
-    ) -> io::Result<()>;
-    fn add_native_library(&mut self, name: Symbol, verbatim: bool);
+    fn add_archive<F>(&mut self, archive: &Path, skip: F) -> io::Result<()>
+    where
+        F: FnMut(&str) -> bool + 'static;
     fn update_symbols(&mut self);
 
     fn build(self);
index f3eb1e04d07dcb0d594c681bc9f25ccdc0252aca..903b630bbd627c8c49fb31869e9491ddf5f11798 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
 use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
 
-use super::archive::ArchiveBuilder;
+use super::archive::{find_library, ArchiveBuilder};
 use super::command::Command;
 use super::linker::{self, Linker};
 use super::rpath::{self, RPathConfig};
@@ -230,6 +230,9 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     tmpdir: &MaybeTempDir,
 ) -> Result<B, ErrorReported> {
     info!("preparing rlib to {:?}", out_filename);
+
+    let lib_search_paths = archive_search_paths(sess);
+
     let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
 
     for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
@@ -262,7 +265,15 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             | NativeLibKind::Unspecified => continue,
         }
         if let Some(name) = lib.name {
-            ab.add_native_library(name, lib.verbatim.unwrap_or(false));
+            let location =
+                find_library(name, lib.verbatim.unwrap_or(false), &lib_search_paths, sess);
+            ab.add_archive(&location, |_| false).unwrap_or_else(|e| {
+                sess.fatal(&format!(
+                    "failed to add native library {}: {}",
+                    location.to_string_lossy(),
+                    e
+                ));
+            });
         }
     }
 
@@ -541,13 +552,35 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
             matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. })
                 && !relevant_lib(sess, lib)
         });
-        ab.add_rlib(
-            path,
-            &name.as_str(),
-            are_upstream_rust_objects_already_included(sess)
-                && !ignored_for_lto(sess, &codegen_results.crate_info, cnum),
-            skip_object_files,
-        )
+
+        let lto = are_upstream_rust_objects_already_included(sess)
+            && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
+
+        // Ignoring obj file starting with the crate name
+        // as simple comparison is not enough - there
+        // might be also an extra name suffix
+        let obj_start = name.as_str().to_owned();
+
+        ab.add_archive(path, move |fname: &str| {
+            // Ignore metadata files, no matter the name.
+            if fname == METADATA_FILENAME {
+                return true;
+            }
+
+            // Don't include Rust objects if LTO is enabled
+            if lto && looks_like_rust_object_file(fname) {
+                return true;
+            }
+
+            // Otherwise if this is *not* a rust object and we're skipping
+            // objects then skip this file
+            if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) {
+                return true;
+            }
+
+            // ok, don't skip this
+            false
+        })
         .unwrap();
 
         all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
@@ -1218,7 +1251,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     sess.split_debuginfo() == SplitDebuginfo::Unpacked
 }
 
-pub fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
+fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
     sess.target_filesearch(PathKind::Native).search_path_dirs()
 }
 
@@ -1803,15 +1836,16 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         add_local_native_libraries(cmd, sess, codegen_results);
     }
 
-    // Rust libraries.
+    // Upstream rust libraries and their nobundle static libraries
     add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
 
-    // Native libraries linked with `#[link]` attributes at and `-l` command line options.
+    // Upstream dymamic native libraries linked with `#[link]` attributes at and `-l`
+    // command line options.
     // If -Zlink-native-libraries=false is set, then the assumption is that an
     // external build system already has the native dependencies defined, and it
     // will provide them to the linker itself.
     if sess.opts.debugging_opts.link_native_libraries {
-        add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
+        add_upstream_native_libraries(cmd, sess, codegen_results);
     }
 
     // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
@@ -2033,7 +2067,7 @@ fn add_local_native_libraries(
     }
 }
 
-/// # Rust Crate linking
+/// # Linking Rust crates and their nobundle static libraries
 ///
 /// Rust crates are not considered at all when creating an rlib output. All dependencies will be
 /// linked when producing the final output (instead of the intermediate rlib version).
@@ -2138,6 +2172,29 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
             Linkage::NotLinked | Linkage::IncludedFromDylib => {}
             Linkage::Static => {
                 add_static_crate::<B>(cmd, sess, codegen_results, tmpdir, crate_type, cnum);
+
+                // Link static native libs with "-bundle" modifier only if the crate they originate from
+                // is being linked statically to the current crate.  If it's linked dynamically
+                // or is an rlib already included via some other dylib crate, the symbols from
+                // native libs will have already been included in that dylib.
+                //
+                // If -Zlink-native-libraries=false is set, then the assumption is that an
+                // external build system already has the native dependencies defined, and it
+                // will provide them to the linker itself.
+                if sess.opts.debugging_opts.link_native_libraries {
+                    // Skip if this library is the same as the last.
+                    let mut last = None;
+                    for lib in &codegen_results.crate_info.native_libraries[&cnum] {
+                        if lib.name.is_some()
+                            && relevant_lib(sess, lib)
+                            && matches!(lib.kind, NativeLibKind::Static { bundle: Some(false), .. })
+                            && last != lib.name
+                        {
+                            cmd.link_staticlib(lib.name.unwrap(), lib.verbatim.unwrap_or(false));
+                            last = lib.name;
+                        }
+                    }
+                }
             }
             Linkage::Dynamic => add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0),
         }
@@ -2310,27 +2367,9 @@ fn add_upstream_native_libraries(
     cmd: &mut dyn Linker,
     sess: &Session,
     codegen_results: &CodegenResults,
-    crate_type: CrateType,
 ) {
-    // Be sure to use a topological sorting of crates because there may be
-    // interdependencies between native libraries. When passing -nodefaultlibs,
-    // for example, almost all native libraries depend on libc, so we have to
-    // make sure that's all the way at the right (liblibc is near the base of
-    // the dependency chain).
-    //
-    // This passes RequireStatic, but the actual requirement doesn't matter,
-    // we're just getting an ordering of crate numbers, we're not worried about
-    // the paths.
-    let (_, data) = codegen_results
-        .crate_info
-        .dependency_formats
-        .iter()
-        .find(|(ty, _)| *ty == crate_type)
-        .expect("failed to find crate type in dependency format list");
-
-    let crates = &codegen_results.crate_info.used_crates;
     let mut last = (NativeLibKind::Unspecified, None);
-    for &cnum in crates {
+    for &cnum in &codegen_results.crate_info.used_crates {
         for lib in codegen_results.crate_info.native_libraries[&cnum].iter() {
             let name = match lib.name {
                 Some(l) => l,
@@ -2352,19 +2391,10 @@ fn add_upstream_native_libraries(
                 NativeLibKind::Framework { as_needed } => {
                     cmd.link_framework(name, as_needed.unwrap_or(true))
                 }
-                NativeLibKind::Static { bundle: Some(false), .. } => {
-                    // Link "static-nobundle" native libs only if the crate they originate from
-                    // is being linked statically to the current crate.  If it's linked dynamically
-                    // or is an rlib already included via some other dylib crate, the symbols from
-                    // native libs will have already been included in that dylib.
-                    if data[cnum.as_usize() - 1] == Linkage::Static {
-                        cmd.link_staticlib(name, verbatim)
-                    }
-                }
-                // ignore statically included native libraries here as we've
-                // already included them when we included the rust library
-                // previously
-                NativeLibKind::Static { bundle: None | Some(true), .. } => {}
+                // ignore static native libraries here as we've
+                // already included them in add_local_native_libraries and
+                // add_upstream_rust_crates
+                NativeLibKind::Static { .. } => {}
                 NativeLibKind::RawDylib => {}
             }
         }
@@ -2485,20 +2515,39 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
         if let LinkerFlavor::Gcc = flavor {
             match ld_impl {
                 LdImpl::Lld => {
-                    let tools_path =
-                        sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
-                    let lld_path = tools_path
-                        .into_iter()
-                        .map(|p| p.join("gcc-ld"))
-                        .find(|p| {
-                            p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
-                        })
-                        .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
-                    cmd.cmd().arg({
-                        let mut arg = OsString::from("-B");
-                        arg.push(lld_path);
-                        arg
-                    });
+                    if sess.target.lld_flavor == LldFlavor::Ld64 {
+                        let tools_path =
+                            sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+                        let ld64_exe = tools_path
+                            .into_iter()
+                            .map(|p| p.join("gcc-ld"))
+                            .map(|p| {
+                                p.join(if sess.host.is_like_windows { "ld64.exe" } else { "ld64" })
+                            })
+                            .find(|p| p.exists())
+                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld64) not found"));
+                        cmd.cmd().arg({
+                            let mut arg = OsString::from("-fuse-ld=");
+                            arg.push(ld64_exe);
+                            arg
+                        });
+                    } else {
+                        let tools_path =
+                            sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+                        let lld_path = tools_path
+                            .into_iter()
+                            .map(|p| p.join("gcc-ld"))
+                            .find(|p| {
+                                p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" })
+                                    .exists()
+                            })
+                            .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
+                        cmd.cmd().arg({
+                            let mut arg = OsString::from("-B");
+                            arg.push(lld_path);
+                            arg
+                        });
+                    }
                 }
             }
         } else {
index a5143a755fe69a237030c4d1a9c3b35f90fafd43..a6bf1d8d1e51a2ef596dc6e2c4532b13a75df1ad 100644 (file)
 use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::middle::lang_items;
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, EntryFnType};
 use rustc_session::Session;
 use rustc_span::symbol::sym;
-use rustc_target::abi::{Align, LayoutOf, VariantIdx};
+use rustc_target::abi::{Align, VariantIdx};
 
 use std::convert::TryFrom;
 use std::ops::{Deref, DerefMut};
@@ -538,12 +538,18 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
     } else if let Some(kind) = tcx.allocator_kind(()) {
         let llmod_id =
             cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
-        let mut modules = backend.new_metadata(tcx, &llmod_id);
+        let mut module_llvm = backend.new_metadata(tcx, &llmod_id);
         tcx.sess.time("write_allocator_module", || {
-            backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some())
+            backend.codegen_allocator(
+                tcx,
+                &mut module_llvm,
+                &llmod_id,
+                kind,
+                tcx.lang_items().oom().is_some(),
+            )
         });
 
-        Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator })
+        Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator })
     } else {
         None
     };
index 81e905b1b5f578279466d7f28feb5ade52ac7147..f0b32c96309d629f90e66a6aaa94c71967404753 100644 (file)
@@ -406,11 +406,11 @@ fn msvc_enum_fallback(
             let dataful_discriminant_range =
                 &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
 
-            let min = dataful_discriminant_range.start();
-            let min = tag.value.size(&tcx).truncate(*min);
+            let min = dataful_discriminant_range.start;
+            let min = tag.value.size(&tcx).truncate(min);
 
-            let max = dataful_discriminant_range.end();
-            let max = tag.value.size(&tcx).truncate(*max);
+            let max = dataful_discriminant_range.end;
+            let max = tag.value.size(&tcx).truncate(max);
 
             let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
 
index b6def164fac631002bc920ed071bf2fb10eba5a2..8d75b2e7a3d4c62a92519e00cf503310c9cc0a75 100644 (file)
@@ -9,8 +9,7 @@
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
-use rustc_middle::ty::layout::HasTyCtxt;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 
 pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
index 58ce31e0c4c9d48747a0a9e0d032862e133f87da..2ca7e8fd7e8e377e05a8a89a52a6c276137625ed 100644 (file)
 use rustc_index::vec::Idx;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::{self, SwitchTargets};
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, HasDataLayout, LayoutOf};
+use rustc_target::abi::{self, HasDataLayout};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -472,10 +472,8 @@ enum AssertIntrinsic {
             let layout = bx.layout_of(ty);
             let do_panic = match intrinsic {
                 Inhabited => layout.abi.is_uninhabited(),
-                // We unwrap as the error type is `!`.
-                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
-                // We unwrap as the error type is `!`.
-                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
+                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true),
+                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
             };
             if do_panic {
                 let msg_str = with_no_trimmed_paths(|| {
@@ -1398,7 +1396,7 @@ fn codegen_transmute(&mut self, bx: &mut Bx, src: &mir::Operand<'tcx>, dst: mir:
                 LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
                 LocalRef::Operand(None) => {
                     let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref()));
-                    assert!(!dst_layout.ty.has_erasable_regions());
+                    assert!(!dst_layout.ty.has_erasable_regions(self.cx.tcx()));
                     let place = PlaceRef::alloca(bx, dst_layout);
                     place.storage_live(bx);
                     self.codegen_transmute_into(bx, src, place);
index 3bbc481b61093fccfa1fe09ae051095f6ebb5aac..e2edd448267175974d734b913086e88f43ebac16 100644 (file)
@@ -216,7 +216,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         let mut allocate_local = |local| {
             let decl = &mir.local_decls[local];
             let layout = bx.layout_of(fx.monomorphize(decl.ty));
-            assert!(!layout.ty.has_erasable_regions());
+            assert!(!layout.ty.has_erasable_regions(cx.tcx()));
 
             if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
                 debug!("alloc: {:?} (return place) -> place", local);
index cfb2befdf913752ffe89b4acd0faf8538badf4e0..5cee25b5cca3b5f9fa5362341f4617aaa21f15b5 100644 (file)
@@ -8,9 +8,9 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ConstValue, Pointer, Scalar};
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Abi, Align, LayoutOf, Size};
+use rustc_target::abi::{Abi, Align, Size};
 
 use std::fmt;
 
index 20be46606a0aad771c585580ccfeaa0f881843a6..b48d6d42b43577d62242d06c0d2fc12b8d396815 100644 (file)
@@ -8,10 +8,10 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::tcx::PlaceTy;
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding};
-use rustc_target::abi::{LayoutOf, VariantIdx, Variants};
+use rustc_target::abi::{VariantIdx, Variants};
 
 #[derive(Copy, Clone, Debug)]
 pub struct PlaceRef<'tcx, V> {
index 65869483025fb7e04f432e4b46807fa788bd2789..3d8ea29160bd0941785274fa746c2883fb2fbae3 100644 (file)
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir;
 use rustc_middle::ty::cast::{CastTy, IntTy};
-use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
-use rustc_target::abi::{Abi, Int, LayoutOf, Variants};
+use rustc_target::abi::{Abi, Int, Variants};
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_rvalue(
@@ -310,15 +310,15 @@ pub fn codegen_rvalue_operand(
 
                                 let er = scalar.valid_range_exclusive(bx.cx());
                                 if er.end != er.start
-                                    && scalar.valid_range.end() >= scalar.valid_range.start()
+                                    && scalar.valid_range.end >= scalar.valid_range.start
                                 {
                                     // We want `table[e as usize ± k]` to not
                                     // have bound checks, and this is the most
                                     // convenient place to put the `assume`s.
-                                    if *scalar.valid_range.start() > 0 {
+                                    if scalar.valid_range.start > 0 {
                                         let enum_value_lower_bound = bx
                                             .cx()
-                                            .const_uint_big(ll_t_in, *scalar.valid_range.start());
+                                            .const_uint_big(ll_t_in, scalar.valid_range.start);
                                         let cmp_start = bx.icmp(
                                             IntPredicate::IntUGE,
                                             llval,
@@ -328,7 +328,7 @@ pub fn codegen_rvalue_operand(
                                     }
 
                                     let enum_value_upper_bound =
-                                        bx.cx().const_uint_big(ll_t_in, *scalar.valid_range.end());
+                                        bx.cx().const_uint_big(ll_t_in, scalar.valid_range.end);
                                     let cmp_end = bx.icmp(
                                         IntPredicate::IntULE,
                                         llval,
index 48d753e0d843564f7d110c16d0ecad2f14206974..5f0f50ae2df1d2c046b44a29a8bbff1add56bf26 100644 (file)
@@ -4,8 +4,7 @@
 use rustc_hir as hir;
 use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::HasTyCtxt;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 
 pub trait MonoItemExt<'a, 'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
index dc4146ec7b58dc132fa1cf454e9fe2a9ae352d70..dbb7e1ee8b17fd68e573850a13a7b427ffaf5e93 100644 (file)
@@ -8,15 +8,14 @@
 use rustc_errors::ErrorReported;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
     Session,
 };
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::Target;
 
 pub use rustc_data_structures::sync::MetadataRef;
@@ -39,12 +38,12 @@ pub trait BackendTypes {
 }
 
 pub trait Backend<'tcx>:
-    Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
+    Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
 {
 }
 
 impl<'tcx, T> Backend<'tcx> for T where
-    Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
+    Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
 {
 }
 
@@ -115,7 +114,8 @@ fn write_compressed_metadata<'tcx>(
     fn codegen_allocator<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
-        mods: &mut Self::Module,
+        module_llvm: &mut Self::Module,
+        module_name: &str,
         kind: AllocatorKind,
         has_alloc_error_handler: bool,
     );
index 2063cb8c52bb10ca105b994288057489918c409a..bc13ca26e2e22059d24130eb298a38f2b8d409c5 100644 (file)
@@ -25,7 +25,7 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" }
 bitflags = "1.2.1"
 measureme = "9.1.0"
 libc = "0.2"
-stacker = "0.1.12"
+stacker = "0.1.14"
 tempfile = "3.2"
 
 [dependencies.parking_lot]
index 4f5d8d7ea48ba36939b84202281a6e14b5157e9a..293ef4caac4007ad1e74bf1b6404f3a6c0d370e6 100644 (file)
@@ -222,6 +222,10 @@ pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool)
                 let msg = "file locks not supported on this platform";
                 Err(io::Error::new(io::ErrorKind::Other, msg))
             }
+
+            pub fn error_unsupported(_err: &io::Error) -> bool {
+                true
+            }
         }
     }
 }
index fe7a256d2100f1f5ad52800c20759dc93a3fb651..5b83ae31247661e7ecf7969b124d909499f568ed 100644 (file)
@@ -26,7 +26,7 @@ fn map_id<F>(self, mut f: F) -> Self
             // inverse of `Box::assume_init()` and should be safe.
             let mut raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast());
             // SAFETY: Write the mapped value back into the `Box`.
-            ptr::write(raw.as_mut_ptr(), f(value));
+            raw.write(f(value));
             // SAFETY: We just initialized `raw`.
             raw.assume_init()
         }
index 5b27a407ad422eb09925e404da83328ba31fc1c9..e7397bf13bad43319c3ebcb0f4874dd74e3cf78e 100644 (file)
@@ -5,7 +5,7 @@
 
 This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut`
 that enables it to bundle a reference together with the owner of the data it points to.
-This allows moving and dropping of a `OwningRef` without needing to recreate the reference.
+This allows moving and dropping of an `OwningRef` without needing to recreate the reference.
 
 This can sometimes be useful because Rust borrowing rules normally prevent
 moving a type that has been moved from. For example, this kind of code gets rejected:
@@ -1146,7 +1146,7 @@ unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut {
 /// Typedef of an owning reference that uses a `String` as the owner.
 pub type StringRef = OwningRef<String, str>;
 
-/// Typedef of an owning reference that uses a `Rc` as the owner.
+/// Typedef of an owning reference that uses an `Rc` as the owner.
 pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
 /// Typedef of an owning reference that uses an `Arc` as the owner.
 pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
@@ -1157,9 +1157,9 @@ unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut {
 pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
 /// Typedef of an owning reference that uses a `MutexGuard` as the owner.
 pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses a `RwLockReadGuard` as the owner.
+/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner.
 pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses a `RwLockWriteGuard` as the owner.
+/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner.
 pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
 
 /// Typedef of a mutable owning reference that uses a `Box` as the owner.
@@ -1173,7 +1173,7 @@ unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut {
 pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
 /// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner.
 pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses a `RwLockWriteGuard` as the owner.
+/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner.
 pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
 
 unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
index 00e304734983ff15a0cb3e78dd76a8649f692508..b5d2d24736cdc4b89d30e9dc4a84e83a84abebc2 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::iter::FromIterator;
 
-/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
+/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`).
 /// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
 /// which uses only a single (null) pointer.
 #[derive(Clone, Encodable, Decodable, Debug)]
index fcc70b2e4c5ff3e600993e2f82e5ea8cb053858e..53053327d0dab276b0c90134b18854a84d0fe483 100644 (file)
@@ -423,10 +423,10 @@ fn run_compiler(
             sess.print_perf_stats();
         }
 
-        if sess.print_fuel_crate.is_some() {
+        if sess.opts.debugging_opts.print_fuel.is_some() {
             eprintln!(
                 "Fuel used by {}: {}",
-                sess.print_fuel_crate.as_ref().unwrap(),
+                sess.opts.debugging_opts.print_fuel.as_ref().unwrap(),
                 sess.print_fuel.load(SeqCst)
             );
         }
index c2e62328cb151e38f4a0a33ce8000980c2c75190..45d91c2047d4193857e2d6569b0593d6becd8c03 100644 (file)
 E0782: include_str!("./error_codes/E0782.md"),
 E0783: include_str!("./error_codes/E0783.md"),
 E0784: include_str!("./error_codes/E0784.md"),
+E0785: include_str!("./error_codes/E0785.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
index 120c96b421104b4d2de741fc9e8f691c0db492ec..ef17b8b4c75c980dbc5cb93a3247bbd9d1d3cc9f 100644 (file)
@@ -6,7 +6,7 @@ Erroneous code example:
 #![feature(lang_items)]
 
 #[lang = "owned_box"]
-struct Foo; // error: duplicate lang item found: `owned_box`
+struct Foo<T>(T); // error: duplicate lang item found: `owned_box`
 ```
 
 Lang items are already implemented in the standard library. Unless you are
index a993ce826a737e0cfada3310469bf4b408bffefa..d4dbfb7a5d8e61c9b680df052e5e49f52a1200df 100644 (file)
@@ -4,8 +4,6 @@ Const parameters cannot depend on type parameters.
 The following is therefore invalid:
 
 ```compile_fail,E0770
-#![feature(const_generics)]
-
 fn const_id<T, const N: T>() -> T { // error
     N
 }
index 91379bfe05c65fe5122667d9b81b85a33d06473e..70d963cd41f21a86162bbd8d88b5d7a2848236fc 100644 (file)
@@ -3,7 +3,7 @@ A non-structural-match type was used as the type of a const generic parameter.
 Erroneous code example:
 
 ```compile_fail,E0741
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 
 struct A;
 
@@ -16,7 +16,7 @@ may be used as the types of const generic parameters.
 To fix the previous code example, we derive `PartialEq` and `Eq`:
 
 ```
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 
 #[derive(PartialEq, Eq)] // We derive both traits here.
 struct A;
index b39163a9de3fd7b63bc2fdc85cac7d72f0f93114..cd8fc481bf0cdceabf5d9c3aa00b1fcff7aaeed0 100644 (file)
@@ -3,7 +3,6 @@ The type of a const parameter references other generic parameters.
 Erroneous code example:
 
 ```compile_fail,E0770
-#![feature(const_generics)]
 fn foo<T, const N: T>() {} // error!
 ```
 
index 824a955f6b3f48933d115c511d9ff4649c807caa..a2a1a20f230336099842c1917e085e8bca85c5b1 100644 (file)
@@ -4,7 +4,7 @@ allowed.
 Erroneous code example:
 
 ```compile_fail,E0771
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 
 fn function_with_str<'a, const STRING: &'a str>() {} // error!
 ```
@@ -13,7 +13,7 @@ To fix this issue, the lifetime in the const generic need to be changed to
 `'static`:
 
 ```
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 
 fn function_with_str<const STRING: &'static str>() {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0785.md b/compiler/rustc_error_codes/src/error_codes/E0785.md
new file mode 100644 (file)
index 0000000..3733205
--- /dev/null
@@ -0,0 +1,30 @@
+An inherent `impl` was written on a dyn auto trait.
+
+Erroneous code example:
+
+```compile_fail,E0785
+#![feature(auto_traits)]
+
+auto trait AutoTrait {}
+
+impl dyn AutoTrait {}
+```
+
+Dyn objects allow any number of auto traits, plus at most one non-auto trait.
+The non-auto trait becomes the "principal trait".
+
+When checking if an impl on a dyn trait is coherent, the principal trait is
+normally the only one considered. Since the erroneous code has no principal
+trait, it cannot be implemented at all.
+
+Working example:
+
+```
+#![feature(auto_traits)]
+
+trait PrincipalTrait {}
+
+auto trait AutoTrait {}
+
+impl dyn PrincipalTrait + AutoTrait + Send {}
+```
index 2253007ce30276928bd9a74db9ee4a6621436dd6..1eb497460e63c053ceec0ea015227513c0dfa79a 100644 (file)
@@ -126,7 +126,7 @@ fn emit_messages_default(
             }
             // owned: line source, line index, annotations
             type Owned = (String, usize, Vec<crate::snippet::Annotation>);
-            let filename = primary_lo.file.name.prefer_local();
+            let filename = source_map.filename_for_diagnostics(&primary_lo.file.name);
             let origin = filename.to_string_lossy();
             let annotated_files: Vec<Owned> = annotated_files
                 .into_iter()
index 8199c44ee2aed21f64697b757d9ac8a560b7eb98..550c1c43530df6090c08f33d5f711f213e641c21 100644 (file)
@@ -9,9 +9,10 @@
 use rustc_serialize::json::Json;
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
+use std::hash::{Hash, Hasher};
 
 #[must_use]
-#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
@@ -24,6 +25,10 @@ pub struct Diagnostic {
     /// as a sort key to sort a buffer of diagnostics.  By default, it is the primary span of
     /// `span` if there is one.  Otherwise, it is `DUMMY_SP`.
     pub sort_span: Span,
+
+    /// If diagnostic is from Lint, custom hash function ignores notes
+    /// otherwise hash is based on the all the fields
+    pub is_lint: bool,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
@@ -91,6 +96,7 @@ pub fn new_with_code(level: Level, code: Option<DiagnosticId>, message: &str) ->
             children: vec![],
             suggestions: vec![],
             sort_span: DUMMY_SP,
+            is_lint: false,
         }
     }
 
@@ -558,6 +564,11 @@ pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
         self
     }
 
+    pub fn set_is_lint(&mut self) -> &mut Self {
+        self.is_lint = true;
+        self
+    }
+
     pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
         self.code = Some(s);
         self
@@ -617,6 +628,42 @@ fn sub_with_highlights(
         let sub = SubDiagnostic { level, message, span, render_span };
         self.children.push(sub);
     }
+
+    /// Fields used for Hash, and PartialEq trait
+    fn keys(
+        &self,
+    ) -> (
+        &Level,
+        &Vec<(String, Style)>,
+        &Option<DiagnosticId>,
+        &MultiSpan,
+        &Vec<CodeSuggestion>,
+        Option<&Vec<SubDiagnostic>>,
+    ) {
+        (
+            &self.level,
+            &self.message,
+            &self.code,
+            &self.span,
+            &self.suggestions,
+            (if self.is_lint { None } else { Some(&self.children) }),
+        )
+    }
+}
+
+impl Hash for Diagnostic {
+    fn hash<H>(&self, state: &mut H)
+    where
+        H: Hasher,
+    {
+        self.keys().hash(state);
+    }
+}
+
+impl PartialEq for Diagnostic {
+    fn eq(&self, other: &Self) -> bool {
+        self.keys() == other.keys()
+    }
 }
 
 impl SubDiagnostic {
index d35b29248033fd75ac3dd6bc4b59f7fad2fe0dd1..c498ce7dbe426aaed3a4396265d9fa61cd3255b5 100644 (file)
@@ -242,6 +242,7 @@ pub fn span_labels(
         sp: S,
         msg: &str,
     ) -> &mut Self);
+    forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
 
     /// See [`Diagnostic::multipart_suggestion()`].
     pub fn multipart_suggestion(
index 25777f4133b94e952176c431190252780eefd0f2..29f352ae58559bf05f68b617c79d569bc735df47 100644 (file)
@@ -1320,7 +1320,7 @@ fn emit_message_default(
                         buffer_msg_line_offset,
                         &format!(
                             "{}:{}:{}",
-                            loc.file.name.prefer_local(),
+                            sm.filename_for_diagnostics(&loc.file.name),
                             sm.doctest_offset_line(&loc.file.name, loc.line),
                             loc.col.0 + 1,
                         ),
@@ -1334,7 +1334,7 @@ fn emit_message_default(
                         0,
                         &format!(
                             "{}:{}:{}: ",
-                            loc.file.name.prefer_local(),
+                            sm.filename_for_diagnostics(&loc.file.name),
                             sm.doctest_offset_line(&loc.file.name, loc.line),
                             loc.col.0 + 1,
                         ),
@@ -1362,12 +1362,12 @@ fn emit_message_default(
                     };
                     format!(
                         "{}:{}{}",
-                        annotated_file.file.name.prefer_local(),
+                        sm.filename_for_diagnostics(&annotated_file.file.name),
                         sm.doctest_offset_line(&annotated_file.file.name, first_line.line_index),
                         col
                     )
                 } else {
-                    format!("{}", annotated_file.file.name.prefer_local())
+                    format!("{}", sm.filename_for_diagnostics(&annotated_file.file.name))
                 };
                 buffer.append(buffer_msg_line_offset + 1, &loc, Style::LineAndColumn);
                 for _ in 0..max_line_num_len {
index 1b6cd04cca642e213efdf22273ddb62a5cfa0d25..dde978cd8c6ceab4b1b7c2927cf8c303d2a0ccdc 100644 (file)
@@ -464,7 +464,7 @@ fn from_span_full(
         });
 
         DiagnosticSpan {
-            file_name: start.file.name.prefer_local().to_string(),
+            file_name: je.sm.filename_for_diagnostics(&start.file.name).to_string(),
             byte_start: start.file.original_relative_byte_pos(span.lo()).0,
             byte_end: start.file.original_relative_byte_pos(span.hi()).0,
             line_start: start.line,
index a48d4fe8bb55adb670f0b8286a0dbdf864b27328..02b6179f89503cac7d4f92ca9bb3df2e14a68416 100644 (file)
@@ -5,9 +5,11 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(crate_visibility_modifier)]
 #![feature(backtrace)]
+#![feature(if_let_guard)]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(nll)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 
 #[macro_use]
 extern crate rustc_macros;
@@ -1027,15 +1029,15 @@ fn print_error_count(&mut self, registry: &Registry) {
             let mut error_codes = self
                 .emitted_diagnostic_codes
                 .iter()
-                .filter_map(|x| match &x {
-                    DiagnosticId::Error(s) => {
-                        if let Ok(Some(_explanation)) = registry.try_find_description(s) {
-                            Some(s.clone())
-                        } else {
-                            None
-                        }
+                .filter_map(|x| {
+                    match &x {
+                    DiagnosticId::Error(s)
+                        if let Ok(Some(_explanation)) = registry.try_find_description(s) =>
+                    {
+                        Some(s.clone())
                     }
                     _ => None,
+                }
                 })
                 .collect::<Vec<_>>();
             if !error_codes.is_empty() {
index a4b7bdd9155ccebd08ce38e2499c587e37556213..35df8aae4babb99d5488b87b99234a5d4ce6d7d1 100644 (file)
@@ -894,6 +894,14 @@ fn cfg_accessible(
     /// Decodes the proc-macro quoted span in the specified crate, with the specified id.
     /// No caching is performed.
     fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span;
+
+    /// The order of items in the HIR is unrelated to the order of
+    /// items in the AST. However, we generate proc macro harnesses
+    /// based on the AST order, and later refer to these harnesses
+    /// from the HIR. This field keeps track of the order in which
+    /// we generated proc macros harnesses, so that we can map
+    /// HIR proc macros items back to their harness items.
+    fn declare_proc_macro(&mut self, id: NodeId);
 }
 
 #[derive(Clone, Default)]
@@ -1113,7 +1121,7 @@ pub fn resolve_path(
                         span,
                         &format!(
                             "cannot resolve relative path in non-file source `{}`",
-                            other.prefer_local()
+                            self.source_map().filename_for_diagnostics(&other)
                         ),
                     ));
                 }
index 824df2757ea90eb2bc231a4483db31d5b695881a..2cc15b3e53f460b93ba8e686e6835fa20a8c0174 100644 (file)
@@ -2,7 +2,7 @@
 
 use rustc_ast::attr;
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, PatKind, UnOp};
+use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 
@@ -153,8 +153,8 @@ pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) ->
         let local = P(ast::Local {
             pat,
             ty: None,
-            init: Some(ex),
             id: ast::DUMMY_NODE_ID,
+            kind: LocalKind::Init(ex),
             span: sp,
             attrs: AttrVec::new(),
             tokens: None,
@@ -167,8 +167,8 @@ pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
         let local = P(ast::Local {
             pat: self.pat_wild(span),
             ty: Some(ty),
-            init: None,
             id: ast::DUMMY_NODE_ID,
+            kind: LocalKind::Decl,
             span,
             attrs: AttrVec::new(),
             tokens: None,
@@ -197,6 +197,7 @@ pub fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> {
             rules: BlockCheckMode::Default,
             span,
             tokens: None,
+            could_be_bare_literal: false,
         })
     }
 
index e09893f7f3884a494c76c8a8ea2ddae91518fc2d..38c099fa4f59ce8556b78a15454bff1d5e7329ae 100644 (file)
@@ -305,15 +305,14 @@ fn can_skip(stream: &AttrAnnotatedTokenStream) -> bool {
                     Some((AttrAnnotatedTokenTree::Delimited(sp, delim, inner), *spacing))
                         .into_iter()
                 }
+                AttrAnnotatedTokenTree::Token(ref token) if let TokenKind::Interpolated(ref nt) = token.kind => {
+                    panic!(
+                        "Nonterminal should have been flattened at {:?}: {:?}",
+                        token.span, nt
+                    );
+                }
                 AttrAnnotatedTokenTree::Token(token) => {
-                    if let TokenKind::Interpolated(nt) = token.kind {
-                        panic!(
-                            "Nonterminal should have been flattened at {:?}: {:?}",
-                            token.span, nt
-                        );
-                    } else {
-                        Some((AttrAnnotatedTokenTree::Token(token), *spacing)).into_iter()
-                    }
+                    Some((AttrAnnotatedTokenTree::Token(token), *spacing)).into_iter()
                 }
             })
             .collect();
index 16e086e32f63da9f3551003da2f614ef2a516828..3ccf9f446a63efa3b556902307568db60fad73e7 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs, MacCall};
+use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
 use rustc_ast_pretty::pprust;
@@ -559,7 +559,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm
         self.cx.force_mode = orig_force_mode;
 
         // Finally incorporate all the expanded macros into the input AST fragment.
-        let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
+        let mut placeholder_expander = PlaceholderExpander::default();
         while let Some(expanded_fragments) = expanded_fragments.pop() {
             for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
                 placeholder_expander
@@ -1061,13 +1061,51 @@ fn take_first_attr(
         attr
     }
 
+    fn take_stmt_bang(
+        &mut self,
+        stmt: ast::Stmt,
+    ) -> Result<(bool, MacCall, Vec<ast::Attribute>), ast::Stmt> {
+        match stmt.kind {
+            StmtKind::MacCall(mac) => {
+                let MacCallStmt { mac, style, attrs, .. } = mac.into_inner();
+                Ok((style == MacStmtStyle::Semicolon, mac, attrs.into()))
+            }
+            StmtKind::Item(ref item) if matches!(item.kind, ItemKind::MacCall(..)) => {
+                match stmt.kind {
+                    StmtKind::Item(item) => match item.into_inner() {
+                        ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
+                            Ok((mac.args.need_semicolon(), mac, attrs))
+                        }
+                        _ => unreachable!(),
+                    },
+                    _ => unreachable!(),
+                }
+            }
+            StmtKind::Semi(ref expr) if matches!(expr.kind, ast::ExprKind::MacCall(..)) => {
+                match stmt.kind {
+                    StmtKind::Semi(expr) => match expr.into_inner() {
+                        ast::Expr { kind: ast::ExprKind::MacCall(mac), attrs, .. } => {
+                            Ok((mac.args.need_semicolon(), mac, attrs.into()))
+                        }
+                        _ => unreachable!(),
+                    },
+                    _ => unreachable!(),
+                }
+            }
+            StmtKind::Local(..) | StmtKind::Empty | StmtKind::Item(..) | StmtKind::Semi(..) => {
+                Err(stmt)
+            }
+            StmtKind::Expr(..) => unreachable!(),
+        }
+    }
+
     fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
         self.cfg.configure(node)
     }
 
     // Detect use of feature-gated or invalid attributes on macro invocations
     // since they will not be detected after macro expansion.
-    fn check_attributes(&mut self, attrs: &[ast::Attribute], call: &MacCall) {
+    fn check_attributes(&self, attrs: &[ast::Attribute], call: &MacCall) {
         let features = self.cx.ecfg.features.unwrap();
         let mut attrs = attrs.iter().peekable();
         let mut span: Option<Span> = None;
@@ -1177,11 +1215,6 @@ fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
         });
     }
 
-    // This is needed in order to set `lint_node_id` for `let` statements
-    fn visit_local(&mut self, local: &mut P<Local>) {
-        assign_id!(self, &mut local.id, || noop_visit_local(local, self));
-    }
-
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
         let mut arm = configure!(self, arm);
 
@@ -1299,31 +1332,39 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
     fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
         let mut stmt = configure!(self, stmt);
 
-        // we'll expand attributes on expressions separately
-        if !stmt.is_expr() {
+        // We pull macro invocations (both attributes and fn-like macro calls) out of their
+        // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
+        // FIXME: invocations in semicolon-less expressions positions are expanded as expressions,
+        // changing that requires some compatibility measures.
+        let mut stmt = if !stmt.is_expr() {
             if let Some(attr) = self.take_first_attr(&mut stmt) {
                 return self
                     .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts)
                     .make_stmts();
             }
-        }
 
-        if let StmtKind::MacCall(mac) = stmt.kind {
-            let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner();
-            self.check_attributes(&attrs, &mac);
-            let mut placeholder =
-                self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts();
-
-            // If this is a macro invocation with a semicolon, then apply that
-            // semicolon to the final statement produced by expansion.
-            if style == MacStmtStyle::Semicolon {
-                if let Some(stmt) = placeholder.pop() {
-                    placeholder.push(stmt.add_trailing_semicolon());
+            let span = stmt.span;
+            match self.take_stmt_bang(stmt) {
+                Ok((add_semicolon, mac, attrs)) => {
+                    self.check_attributes(&attrs, &mac);
+                    let mut stmts =
+                        self.collect_bang(mac, span, AstFragmentKind::Stmts).make_stmts();
+
+                    // If this is a macro invocation with a semicolon, then apply that
+                    // semicolon to the final statement produced by expansion.
+                    if add_semicolon {
+                        if let Some(stmt) = stmts.pop() {
+                            stmts.push(stmt.add_trailing_semicolon());
+                        }
+                    }
+
+                    return stmts;
                 }
+                Err(stmt) => stmt,
             }
-
-            return placeholder;
-        }
+        } else {
+            stmt
+        };
 
         // The only way that we can end up with a `MacCall` expression statement,
         // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the
@@ -1338,14 +1379,7 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
             }
         }
 
-        // The placeholder expander gives ids to statements, so we avoid folding the id here.
-        // We don't use `assign_id!` - it will be called when we visit statement's contents
-        // (e.g. an expression, item, or local)
-        let ast::Stmt { id, kind, span } = stmt;
-        let res = noop_flat_map_stmt_kind(kind, self)
-            .into_iter()
-            .map(|kind| ast::Stmt { id, kind, span })
-            .collect();
+        let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self));
 
         self.cx.current_expansion.is_trailing_mac = false;
         res
index efed41de23a89ebf23b7f0c86841db93167d20f5..c6dc66e99fe940d137ae81b14e213d08e652b5d3 100644 (file)
@@ -1,12 +1,16 @@
+#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(destructuring_assignment)]
 #![feature(format_args_capture)]
+#![feature(if_let_guard)]
 #![feature(iter_zip)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
 #![feature(try_blocks)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
+#![recursion_limit = "256"]
 
 #[macro_use]
 extern crate rustc_macros;
index e0c62388fe0ce7f4f49bf6e2392de4cff166ad14..f8491654f39e31301bd74aad8465c9a0e80aa708 100644 (file)
@@ -1221,7 +1221,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
 
 fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
     match *tt {
-        mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token),
+        mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token).into(),
         mbe::TokenTree::MetaVar(_, name) => format!("${}", name),
         mbe::TokenTree::MetaVarDecl(_, name, Some(kind)) => format!("${}:{}", name, kind),
         mbe::TokenTree::MetaVarDecl(_, name, None) => format!("${}:", name),
index 4d777049f0d627614d9d322fa7b47d0f175c7753..60d653ac8b6f9be426af54ac13c47fe76aaecf46 100644 (file)
@@ -86,13 +86,12 @@ pub enum ModError<'a> {
     inline: Inline,
 ) -> (PathBuf, DirOwnership) {
     match inline {
+        Inline::Yes if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) => {
+            // For inline modules file path from `#[path]` is actually the directory path
+            // for historical reasons, so we don't pop the last segment here.
+            (file_path, DirOwnership::Owned { relative: None })
+        }
         Inline::Yes => {
-            if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
-                // For inline modules file path from `#[path]` is actually the directory path
-                // for historical reasons, so we don't pop the last segment here.
-                return (file_path, DirOwnership::Owned { relative: None });
-            }
-
             // We have to push on the current module name in the case of relative
             // paths in order to ensure that any additional module paths from inline
             // `mod x { ... }` come after the relative extension.
index 6586ba138fb9956c61baf25f0eb13edd301cdbd5..8e78fcbb8dbc14a40110def4bda0c03506a63947 100644 (file)
@@ -1,4 +1,3 @@
-use crate::base::ExtCtxt;
 use crate::expand::{AstFragment, AstFragmentKind};
 
 use rustc_ast as ast;
@@ -175,17 +174,12 @@ fn mac_placeholder() -> ast::MacCall {
     }
 }
 
-pub struct PlaceholderExpander<'a, 'b> {
+#[derive(Default)]
+pub struct PlaceholderExpander {
     expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
-    cx: &'a mut ExtCtxt<'b>,
-    monotonic: bool,
 }
 
-impl<'a, 'b> PlaceholderExpander<'a, 'b> {
-    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
-        PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
-    }
-
+impl PlaceholderExpander {
     pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
         fragment.mut_visit_with(self);
         self.expanded_fragments.insert(id, fragment);
@@ -196,7 +190,7 @@ fn remove(&mut self, id: ast::NodeId) -> AstFragment {
     }
 }
 
-impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
+impl MutVisitor for PlaceholderExpander {
     fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
         if arm.is_placeholder {
             self.remove(arm.id).make_arms()
@@ -360,15 +354,4 @@ fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
             _ => noop_visit_ty(ty, self),
         }
     }
-
-    fn visit_block(&mut self, block: &mut P<ast::Block>) {
-        noop_visit_block(block, self);
-
-        for stmt in block.stmts.iter_mut() {
-            if self.monotonic {
-                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
-                stmt.id = self.cx.resolver.next_node_id();
-            }
-        }
-    }
 }
index 42ae8e972c274ee8c61a703842d53fae2731a7b3..55700f7b0d495e119b07b2fda73c744314082cce 100644 (file)
@@ -178,18 +178,19 @@ macro_rules! op {
                 tt!(Punct::new('#', false))
             }
 
+            Interpolated(nt)
+                if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) =>
+            {
+                TokenTree::Ident(Ident::new(rustc.sess, name.name, is_raw, name.span))
+            }
             Interpolated(nt) => {
-                if let Some((name, is_raw)) = ident_name_compatibility_hack(&nt, span, rustc) {
-                    TokenTree::Ident(Ident::new(rustc.sess, name.name, is_raw, name.span))
-                } else {
-                    let stream = nt_to_tokenstream(&nt, rustc.sess, CanSynthesizeMissingTokens::No);
-                    TokenTree::Group(Group {
-                        delimiter: Delimiter::None,
-                        stream,
-                        span: DelimSpan::from_single(span),
-                        flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess),
-                    })
-                }
+                let stream = nt_to_tokenstream(&nt, rustc.sess, CanSynthesizeMissingTokens::No);
+                TokenTree::Group(Group {
+                    delimiter: Delimiter::None,
+                    stream,
+                    span: DelimSpan::from_single(span),
+                    flatten: crate::base::pretty_printing_compatibility_hack(&nt, rustc.sess),
+                })
             }
 
             OpenDelim(..) | CloseDelim(..) => unreachable!(),
index 18294dfad240df6d1f921e95dd6bb0141667d3e3..725f8b8763af17d3d048395884ede1d07caec3c3 100644 (file)
@@ -273,7 +273,7 @@ macro_rules! declare_features {
     /// Allows patterns with concurrent by-move and by-ref bindings.
     /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
     (accepted, move_ref_pattern, "1.49.0", Some(68354), None),
-    /// The smallest useful subset of `const_generics`.
+    /// The smallest useful subset of const generics.
     (accepted, min_const_generics, "1.51.0", Some(74878), None),
     /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
     (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None),
index 2e4b122f80cbbb33ceb7a2f8a14236b192b4a5df..a3807a2bb9fde64cb5a3a6e2574de2a9176f145f 100644 (file)
@@ -71,7 +71,7 @@ pub fn enabled(&self, feature: Symbol) -> bool {
             }
 
             pub fn unordered_const_ty_params(&self) -> bool {
-                self.const_generics || self.const_generics_defaults
+                self.const_generics_defaults || self.generic_const_exprs || self.adt_const_params
             }
 
             /// Some features are known to be incomplete and using them is likely to have
@@ -453,9 +453,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using `#[ffi_returns_twice]` on foreign functions.
     (active, ffi_returns_twice, "1.34.0", Some(58314), None),
 
-    /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
-    (incomplete, const_generics, "1.34.0", Some(44580), None),
-
     /// Allows using `#[optimize(X)]`.
     (active, optimize_attribute, "1.34.0", Some(54882), None),
 
@@ -515,9 +512,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows `impl const Trait for T` syntax.
     (active, const_trait_impl, "1.42.0", Some(67792), None),
 
-    /// Allows `T: ?const Trait` syntax in bounds.
-    (incomplete, const_trait_bound_opt_out, "1.42.0", Some(67794), None),
-
     /// Allows the use of `no_sanitize` attribute.
     (active, no_sanitize, "1.42.0", Some(39699), None),
 
@@ -548,14 +542,8 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows capturing variables in scope using format_args!
     (active, format_args_capture, "1.46.0", Some(67984), None),
 
-    /// Lazily evaluate constants. This allows constants to depend on type parameters.
-    (incomplete, lazy_normalization_consts, "1.46.0", Some(72219), None),
-
     /// Allows `if let` guard in match arms.
-    (incomplete, if_let_guard, "1.47.0", Some(51114), None),
-
-    /// Allows non-trivial generic constants which have to be manually propagated upwards.
-    (incomplete, const_evaluatable_checked, "1.48.0", Some(76560), None),
+    (active, if_let_guard, "1.47.0", Some(51114), None),
 
     /// Allows basic arithmetic on floating point types in a `const fn`.
     (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
@@ -682,6 +670,15 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using doc(primitive) without a future-incompat warning
     (active, doc_primitive, "1.56.0", Some(88070), None),
 
+    /// Allows non-trivial generic constants which have to have wfness manually propagated to callers
+    (incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
+
+    /// Allows additional const parameter types, such as `&'static str` or user defined types
+    (incomplete, adt_const_params, "1.56.0", Some(44580), None),
+
+    /// Allows `let...else` statements.
+    (active, let_else, "1.56.0", Some(87335), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index 5cadbd9e5cf7198bf87c908d4de5e2dff56818fa..8e498a5446ea8c3270b0e27b13078d30a554504b 100644 (file)
@@ -102,6 +102,9 @@ macro_rules! declare_features {
     (removed, extern_in_paths, "1.33.0", Some(55600), None,
      Some("subsumed by `::foo::bar` paths")),
     (removed, quote, "1.33.0", Some(29601), None, None),
+    /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
+    (removed, const_generics, "1.34.0", Some(44580), None,
+     Some("removed in favor of `#![feature(adt_const_params]` and `#![feature(generic_const_exprs)]`")),
     /// Allows `[x; N]` where `x` is a constant (RFC 2203).
     (removed, const_in_array_repeat_expressions,  "1.37.0", Some(49147), None,
      Some("removed due to causing promotable bugs")),
@@ -123,11 +126,18 @@ macro_rules! declare_features {
     /// Allows overlapping impls of marker traits.
     (removed, overlapping_marker_traits, "1.42.0", Some(29864), None,
      Some("removed in favor of `#![feature(marker_trait_attr)]`")),
+    /// Allows `T: ?const Trait` syntax in bounds.
+    (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None,
+     Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")),
     /// Allows `#[no_debug]`.
     (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
+    /// Lazily evaluate constants. This allows constants to depend on type parameters.
+    (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
     /// Allows comparing raw pointers during const eval.
     (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
      Some("cannot be allowed in const eval in any meaningful way")),
+    /// Allows non-trivial generic constants which have to be manually propagated upwards.
+    (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")),
     /// Allows using the `#[link_args]` attribute.
     (removed, link_args, "1.53.0", Some(29596), None,
      Some("removed in favor of using `-C link-arg=ARG` on command line, \
index c4cff79f6c525c5509821b620c4948b43334e08d..3e8b98e9f5493dd146664a8f2820670e56530aaa 100644 (file)
@@ -9,8 +9,8 @@
 /// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro.
 #[macro_export]
 macro_rules! arena_types {
-    ($macro:path, $args:tt, $tcx:lifetime) => (
-        $macro!($args, [
+    ($macro:path, $tcx:lifetime) => (
+        $macro!([
             // HIR types
             [few] hir_krate: rustc_hir::Crate<$tcx>,
             [] arm: rustc_hir::Arm<$tcx>,
@@ -35,7 +35,6 @@ macro_rules! arena_types {
             [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
             [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
             [] local: rustc_hir::Local<$tcx>,
-            [few] macro_def: rustc_hir::MacroDef<$tcx>,
             [few] mod_: rustc_hir::Mod<$tcx>,
             [] param: rustc_hir::Param<$tcx>,
             [] pat: rustc_hir::Pat<$tcx>,
index 3816888db1062d7e4a1012f8d952d08391803fc1..853415c4173b561d26ff7e1a7cb6e9ff7d663204 100644 (file)
@@ -307,7 +307,7 @@ pub enum Res<Id = hir::HirId> {
     /// We do however allow `Self` in repeat expression even if it is generic to not break code
     /// which already works on stable while causing the `const_evaluatable_unchecked` future compat lint.
     ///
-    /// FIXME(lazy_normalization_consts): Remove this bodge once that feature is stable.
+    /// FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
     SelfTy(
         /// Optionally, the trait associated with this `Self` type.
         Option<DefId>,
index 888d1c1832b09d2e00e4a6bc2c6b5676f5e6ee2f..21fe894c6fcd3d12838e94bc7f4b3d7981dce5e2 100644 (file)
@@ -670,25 +670,12 @@ pub struct ModuleItems {
 /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 #[derive(Debug)]
 pub struct Crate<'hir> {
-    // Attributes from non-exported macros, kept only for collecting the library feature list.
-    pub non_exported_macro_attrs: &'hir [Attribute],
-
     pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
-    pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
-
-    /// A list of the body ids written out in the order in which they
-    /// appear in the crate. If you're going to process all the bodies
-    /// in the crate, you should iterate over this list rather than the keys
-    /// of bodies.
-    pub body_ids: Vec<BodyId>,
 
     /// A list of modules written out in the order in which they
     /// appear in the crate. This includes the main crate module.
     pub modules: BTreeMap<LocalDefId, ModuleItems>,
-    /// A list of proc macro HirIds, written out in the order in which
-    /// they are declared in the static array generated by proc_macro_harness.
-    pub proc_macros: Vec<HirId>,
 
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
@@ -743,7 +730,7 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
                 OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
                 OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
                 OwnerNode::TraitItem(item) => visitor.visit_trait_item(item),
-                OwnerNode::MacroDef(_) | OwnerNode::Crate(_) => {}
+                OwnerNode::Crate(_) => {}
             }
         }
     }
@@ -758,7 +745,7 @@ pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
             Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item),
             Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item),
             Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item),
-            Some(OwnerNode::MacroDef(_)) | Some(OwnerNode::Crate(_)) | None => {}
+            Some(OwnerNode::Crate(_)) | None => {}
         })
     }
 
@@ -768,32 +755,6 @@ pub fn items<'hir>(&'hir self) -> impl Iterator<Item = &'hir Item<'hir>> + 'hir
             _ => None,
         })
     }
-
-    pub fn exported_macros<'hir>(&'hir self) -> impl Iterator<Item = &'hir MacroDef<'hir>> + 'hir {
-        self.owners.iter().filter_map(|owner| match owner {
-            Some(OwnerNode::MacroDef(macro_def)) => Some(*macro_def),
-            _ => None,
-        })
-    }
-}
-
-/// A macro definition, in this crate or imported from another.
-///
-/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Debug)]
-pub struct MacroDef<'hir> {
-    pub ident: Ident,
-    pub vis: Visibility<'hir>,
-    pub def_id: LocalDefId,
-    pub span: Span,
-    pub ast: ast::MacroDef,
-}
-
-impl MacroDef<'_> {
-    #[inline]
-    pub fn hir_id(&self) -> HirId {
-        HirId::make_owner(self.def_id)
-    }
 }
 
 /// A block of statements `{ .. }`, which may have a label (in this case the
@@ -1216,6 +1177,7 @@ pub struct Arm<'hir> {
 #[derive(Debug, HashStable_Generic)]
 pub enum Guard<'hir> {
     If(&'hir Expr<'hir>),
+    // FIXME use ExprKind::Let for this.
     IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>),
 }
 
@@ -2386,6 +2348,7 @@ pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
 #[derive(Debug, HashStable_Generic)]
 pub struct InlineAsm<'hir> {
     pub template: &'hir [InlineAsmTemplatePiece],
+    pub template_strs: &'hir [(Symbol, Option<Symbol>, Span)],
     pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
     pub options: InlineAsmOptions,
     pub line_spans: &'hir [Span],
@@ -2601,7 +2564,7 @@ pub struct PolyTraitRef<'hir> {
 
 pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
 
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum VisibilityKind<'hir> {
     Public,
     Crate(CrateSugar),
@@ -2790,6 +2753,8 @@ pub enum ItemKind<'hir> {
     Const(&'hir Ty<'hir>, BodyId),
     /// A function declaration.
     Fn(FnSig<'hir>, Generics<'hir>, BodyId),
+    /// A MBE macro definition (`macro_rules!` or `macro`).
+    Macro(ast::MacroDef),
     /// A module.
     Mod(Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
@@ -2855,6 +2820,7 @@ pub fn descr(&self) -> &'static str {
             ItemKind::Static(..) => "static item",
             ItemKind::Const(..) => "constant item",
             ItemKind::Fn(..) => "function",
+            ItemKind::Macro(..) => "macro",
             ItemKind::Mod(..) => "module",
             ItemKind::ForeignMod { .. } => "extern block",
             ItemKind::GlobalAsm(..) => "global asm item",
@@ -2995,7 +2961,6 @@ pub enum OwnerNode<'hir> {
     ForeignItem(&'hir ForeignItem<'hir>),
     TraitItem(&'hir TraitItem<'hir>),
     ImplItem(&'hir ImplItem<'hir>),
-    MacroDef(&'hir MacroDef<'hir>),
     Crate(&'hir Mod<'hir>),
 }
 
@@ -3005,8 +2970,7 @@ pub fn ident(&self) -> Option<Ident> {
             OwnerNode::Item(Item { ident, .. })
             | OwnerNode::ForeignItem(ForeignItem { ident, .. })
             | OwnerNode::ImplItem(ImplItem { ident, .. })
-            | OwnerNode::TraitItem(TraitItem { ident, .. })
-            | OwnerNode::MacroDef(MacroDef { ident, .. }) => Some(*ident),
+            | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
             OwnerNode::Crate(..) => None,
         }
     }
@@ -3017,7 +2981,6 @@ pub fn span(&self) -> Span {
             | OwnerNode::ForeignItem(ForeignItem { span, .. })
             | OwnerNode::ImplItem(ImplItem { span, .. })
             | OwnerNode::TraitItem(TraitItem { span, .. })
-            | OwnerNode::MacroDef(MacroDef { span, .. })
             | OwnerNode::Crate(Mod { inner: span, .. }) => *span,
         }
     }
@@ -3061,8 +3024,7 @@ pub fn def_id(self) -> LocalDefId {
             OwnerNode::Item(Item { def_id, .. })
             | OwnerNode::TraitItem(TraitItem { def_id, .. })
             | OwnerNode::ImplItem(ImplItem { def_id, .. })
-            | OwnerNode::ForeignItem(ForeignItem { def_id, .. })
-            | OwnerNode::MacroDef(MacroDef { def_id, .. }) => *def_id,
+            | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id,
             OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
         }
     }
@@ -3094,13 +3056,6 @@ pub fn expect_trait_item(self) -> &'hir TraitItem<'hir> {
             _ => panic!(),
         }
     }
-
-    pub fn expect_macro_def(self) -> &'hir MacroDef<'hir> {
-        match self {
-            OwnerNode::MacroDef(n) => n,
-            _ => panic!(),
-        }
-    }
 }
 
 impl<'hir> Into<OwnerNode<'hir>> for &'hir Item<'hir> {
@@ -3127,12 +3082,6 @@ fn into(self) -> OwnerNode<'hir> {
     }
 }
 
-impl<'hir> Into<OwnerNode<'hir>> for &'hir MacroDef<'hir> {
-    fn into(self) -> OwnerNode<'hir> {
-        OwnerNode::MacroDef(self)
-    }
-}
-
 impl<'hir> Into<Node<'hir>> for OwnerNode<'hir> {
     fn into(self) -> Node<'hir> {
         match self {
@@ -3140,7 +3089,6 @@ fn into(self) -> Node<'hir> {
             OwnerNode::ForeignItem(n) => Node::ForeignItem(n),
             OwnerNode::ImplItem(n) => Node::ImplItem(n),
             OwnerNode::TraitItem(n) => Node::TraitItem(n),
-            OwnerNode::MacroDef(n) => Node::MacroDef(n),
             OwnerNode::Crate(n) => Node::Crate(n),
         }
     }
@@ -3166,7 +3114,6 @@ pub enum Node<'hir> {
     Arm(&'hir Arm<'hir>),
     Block(&'hir Block<'hir>),
     Local(&'hir Local<'hir>),
-    MacroDef(&'hir MacroDef<'hir>),
 
     /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
     /// with synthesized constructors.
@@ -3182,6 +3129,20 @@ pub enum Node<'hir> {
 }
 
 impl<'hir> Node<'hir> {
+    /// Get the identifier of this `Node`, if applicable.
+    ///
+    /// # Edge cases
+    ///
+    /// Calling `.ident()` on a [`Node::Ctor`] will return `None`
+    /// because `Ctor`s do not have identifiers themselves.
+    /// Instead, call `.ident()` on the parent struct/variant, like so:
+    ///
+    /// ```ignore (illustrative)
+    /// ctor
+    ///     .ctor_hir_id()
+    ///     .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
+    ///     .and_then(|parent| parent.ident())
+    /// ```
     pub fn ident(&self) -> Option<Ident> {
         match self {
             Node::TraitItem(TraitItem { ident, .. })
@@ -3189,9 +3150,25 @@ pub fn ident(&self) -> Option<Ident> {
             | Node::ForeignItem(ForeignItem { ident, .. })
             | Node::Field(FieldDef { ident, .. })
             | Node::Variant(Variant { ident, .. })
-            | Node::MacroDef(MacroDef { ident, .. })
-            | Node::Item(Item { ident, .. }) => Some(*ident),
-            _ => None,
+            | Node::Item(Item { ident, .. })
+            | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident),
+            Node::Lifetime(lt) => Some(lt.name.ident()),
+            Node::GenericParam(p) => Some(p.name.ident()),
+            Node::Param(..)
+            | Node::AnonConst(..)
+            | Node::Expr(..)
+            | Node::Stmt(..)
+            | Node::Block(..)
+            | Node::Ctor(..)
+            | Node::Pat(..)
+            | Node::Binding(..)
+            | Node::Arm(..)
+            | Node::Local(..)
+            | Node::Visibility(..)
+            | Node::Crate(..)
+            | Node::Ty(..)
+            | Node::TraitRef(..)
+            | Node::Infer(..) => None,
         }
     }
 
@@ -3233,8 +3210,7 @@ pub fn hir_id(&self) -> Option<HirId> {
             Node::Item(Item { def_id, .. })
             | Node::TraitItem(TraitItem { def_id, .. })
             | Node::ImplItem(ImplItem { def_id, .. })
-            | Node::ForeignItem(ForeignItem { def_id, .. })
-            | Node::MacroDef(MacroDef { def_id, .. }) => Some(HirId::make_owner(*def_id)),
+            | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)),
             Node::Field(FieldDef { hir_id, .. })
             | Node::AnonConst(AnonConst { hir_id, .. })
             | Node::Expr(Expr { hir_id, .. })
@@ -3294,7 +3270,6 @@ pub fn as_owner(self) -> Option<OwnerNode<'hir>> {
             Node::ForeignItem(i) => Some(OwnerNode::ForeignItem(i)),
             Node::TraitItem(i) => Some(OwnerNode::TraitItem(i)),
             Node::ImplItem(i) => Some(OwnerNode::ImplItem(i)),
-            Node::MacroDef(i) => Some(OwnerNode::MacroDef(i)),
             Node::Crate(i) => Some(OwnerNode::Crate(i)),
             _ => None,
         }
index 7f153867596ec8439a6077b8dfab9a2b9dc7199a..2dd49eba4427a8bd00305c8f7633fe3814c69ab7 100644 (file)
@@ -32,7 +32,6 @@
 //! example generator inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use crate::hir_id::CRATE_HIR_ID;
 use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
 use rustc_ast::walk_list;
 use rustc_ast::{Attribute, Label};
@@ -466,9 +465,6 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
         walk_assoc_type_binding(self, type_binding)
     }
     fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
-    fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
-        walk_macro_def(self, macro_def)
-    }
     fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
         walk_vis(self, vis)
     }
@@ -480,23 +476,6 @@ fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
     }
 }
 
-/// Walks the contents of a crate. See also `Crate::visit_all_items`.
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
-    let top_mod = krate.module();
-    visitor.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
-    walk_list!(visitor, visit_macro_def, krate.exported_macros());
-    for (&id, attrs) in krate.attrs.iter() {
-        for a in *attrs {
-            visitor.visit_attribute(id, a)
-        }
-    }
-}
-
-pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
-    visitor.visit_id(macro_def.hir_id());
-    visitor.visit_ident(macro_def.ident);
-}
-
 pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
     visitor.visit_id(mod_hir_id);
     for &item_id in module.item_ids {
@@ -586,6 +565,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             item.span,
             item.hir_id(),
         ),
+        ItemKind::Macro(_) => {
+            visitor.visit_id(item.hir_id());
+        }
         ItemKind::Mod(ref module) => {
             // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
             visitor.visit_mod(module, item.span, item.hir_id())
index 55000ae7e59d4d7b1e7b57b0c912488e7b72a316..b85ed0cb4bbe59ecc1b2e707342cea7aefbc4eb2 100644 (file)
@@ -38,7 +38,7 @@ macro_rules! expand_group {
 // So you probably just want to nip down to the end.
 macro_rules! language_item_table {
     (
-        $( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr; )*
+        $( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
     ) => {
 
         enum_from_u32! {
@@ -72,6 +72,12 @@ pub fn group(self) -> Option<LangItemGroup> {
                     $( LangItem::$variant => expand_group!($($group)*), )*
                 }
             }
+
+            pub fn required_generics(&self) -> GenericRequirement {
+                match self {
+                    $( LangItem::$variant => $generics, )*
+                }
+            }
         }
 
         /// All of the language items, defined or not.
@@ -165,108 +171,108 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
 }
 
 language_item_table! {
-//  Variant name,            Name,                     Method name,                Target;
-    Bool,                    sym::bool,                bool_impl,                  Target::Impl;
-    Char,                    sym::char,                char_impl,                  Target::Impl;
-    Str,                     sym::str,                 str_impl,                   Target::Impl;
-    Array,                   sym::array,               array_impl,                 Target::Impl;
-    Slice,                   sym::slice,               slice_impl,                 Target::Impl;
-    SliceU8,                 sym::slice_u8,            slice_u8_impl,              Target::Impl;
-    StrAlloc,                sym::str_alloc,           str_alloc_impl,             Target::Impl;
-    SliceAlloc,              sym::slice_alloc,         slice_alloc_impl,           Target::Impl;
-    SliceU8Alloc,            sym::slice_u8_alloc,      slice_u8_alloc_impl,        Target::Impl;
-    ConstPtr,                sym::const_ptr,           const_ptr_impl,             Target::Impl;
-    MutPtr,                  sym::mut_ptr,             mut_ptr_impl,               Target::Impl;
-    ConstSlicePtr,           sym::const_slice_ptr,     const_slice_ptr_impl,       Target::Impl;
-    MutSlicePtr,             sym::mut_slice_ptr,       mut_slice_ptr_impl,         Target::Impl;
-    I8,                      sym::i8,                  i8_impl,                    Target::Impl;
-    I16,                     sym::i16,                 i16_impl,                   Target::Impl;
-    I32,                     sym::i32,                 i32_impl,                   Target::Impl;
-    I64,                     sym::i64,                 i64_impl,                   Target::Impl;
-    I128,                    sym::i128,                i128_impl,                  Target::Impl;
-    Isize,                   sym::isize,               isize_impl,                 Target::Impl;
-    U8,                      sym::u8,                  u8_impl,                    Target::Impl;
-    U16,                     sym::u16,                 u16_impl,                   Target::Impl;
-    U32,                     sym::u32,                 u32_impl,                   Target::Impl;
-    U64,                     sym::u64,                 u64_impl,                   Target::Impl;
-    U128,                    sym::u128,                u128_impl,                  Target::Impl;
-    Usize,                   sym::usize,               usize_impl,                 Target::Impl;
-    F32,                     sym::f32,                 f32_impl,                   Target::Impl;
-    F64,                     sym::f64,                 f64_impl,                   Target::Impl;
-    F32Runtime,              sym::f32_runtime,         f32_runtime_impl,           Target::Impl;
-    F64Runtime,              sym::f64_runtime,         f64_runtime_impl,           Target::Impl;
-
-    Sized,                   sym::sized,               sized_trait,                Target::Trait;
-    Unsize,                  sym::unsize,              unsize_trait,               Target::Trait;
+//  Variant name,            Name,                     Method name,                Target                  Generic requirements;
+    Bool,                    sym::bool,                bool_impl,                  Target::Impl,           GenericRequirement::None;
+    Char,                    sym::char,                char_impl,                  Target::Impl,           GenericRequirement::None;
+    Str,                     sym::str,                 str_impl,                   Target::Impl,           GenericRequirement::None;
+    Array,                   sym::array,               array_impl,                 Target::Impl,           GenericRequirement::None;
+    Slice,                   sym::slice,               slice_impl,                 Target::Impl,           GenericRequirement::None;
+    SliceU8,                 sym::slice_u8,            slice_u8_impl,              Target::Impl,           GenericRequirement::None;
+    StrAlloc,                sym::str_alloc,           str_alloc_impl,             Target::Impl,           GenericRequirement::None;
+    SliceAlloc,              sym::slice_alloc,         slice_alloc_impl,           Target::Impl,           GenericRequirement::None;
+    SliceU8Alloc,            sym::slice_u8_alloc,      slice_u8_alloc_impl,        Target::Impl,           GenericRequirement::None;
+    ConstPtr,                sym::const_ptr,           const_ptr_impl,             Target::Impl,           GenericRequirement::None;
+    MutPtr,                  sym::mut_ptr,             mut_ptr_impl,               Target::Impl,           GenericRequirement::None;
+    ConstSlicePtr,           sym::const_slice_ptr,     const_slice_ptr_impl,       Target::Impl,           GenericRequirement::None;
+    MutSlicePtr,             sym::mut_slice_ptr,       mut_slice_ptr_impl,         Target::Impl,           GenericRequirement::None;
+    I8,                      sym::i8,                  i8_impl,                    Target::Impl,           GenericRequirement::None;
+    I16,                     sym::i16,                 i16_impl,                   Target::Impl,           GenericRequirement::None;
+    I32,                     sym::i32,                 i32_impl,                   Target::Impl,           GenericRequirement::None;
+    I64,                     sym::i64,                 i64_impl,                   Target::Impl,           GenericRequirement::None;
+    I128,                    sym::i128,                i128_impl,                  Target::Impl,           GenericRequirement::None;
+    Isize,                   sym::isize,               isize_impl,                 Target::Impl,           GenericRequirement::None;
+    U8,                      sym::u8,                  u8_impl,                    Target::Impl,           GenericRequirement::None;
+    U16,                     sym::u16,                 u16_impl,                   Target::Impl,           GenericRequirement::None;
+    U32,                     sym::u32,                 u32_impl,                   Target::Impl,           GenericRequirement::None;
+    U64,                     sym::u64,                 u64_impl,                   Target::Impl,           GenericRequirement::None;
+    U128,                    sym::u128,                u128_impl,                  Target::Impl,           GenericRequirement::None;
+    Usize,                   sym::usize,               usize_impl,                 Target::Impl,           GenericRequirement::None;
+    F32,                     sym::f32,                 f32_impl,                   Target::Impl,           GenericRequirement::None;
+    F64,                     sym::f64,                 f64_impl,                   Target::Impl,           GenericRequirement::None;
+    F32Runtime,              sym::f32_runtime,         f32_runtime_impl,           Target::Impl,           GenericRequirement::None;
+    F64Runtime,              sym::f64_runtime,         f64_runtime_impl,           Target::Impl,           GenericRequirement::None;
+
+    Sized,                   sym::sized,               sized_trait,                Target::Trait,          GenericRequirement::Exact(0);
+    Unsize,                  sym::unsize,              unsize_trait,               Target::Trait,          GenericRequirement::Minimum(1);
     /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
-    StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait;
+    StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait,          GenericRequirement::None;
     /// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
-    StructuralTeq,           sym::structural_teq,      structural_teq_trait,       Target::Trait;
-    Copy,                    sym::copy,                copy_trait,                 Target::Trait;
-    Clone,                   sym::clone,               clone_trait,                Target::Trait;
-    Sync,                    sym::sync,                sync_trait,                 Target::Trait;
-    DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait;
+    StructuralTeq,           sym::structural_teq,      structural_teq_trait,       Target::Trait,          GenericRequirement::None;
+    Copy,                    sym::copy,                copy_trait,                 Target::Trait,          GenericRequirement::Exact(0);
+    Clone,                   sym::clone,               clone_trait,                Target::Trait,          GenericRequirement::None;
+    Sync,                    sym::sync,                sync_trait,                 Target::Trait,          GenericRequirement::Exact(0);
+    DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait,          GenericRequirement::None;
     /// The associated item of the [`DiscriminantKind`] trait.
-    Discriminant,            sym::discriminant_type,   discriminant_type,          Target::AssocTy;
-
-    PointeeTrait,            sym::pointee_trait,       pointee_trait,              Target::Trait;
-    Metadata,                sym::metadata_type,       metadata_type,              Target::AssocTy;
-    DynMetadata,             sym::dyn_metadata,        dyn_metadata,               Target::Struct;
-
-    Freeze,                  sym::freeze,              freeze_trait,               Target::Trait;
-
-    Drop,                    sym::drop,                drop_trait,                 Target::Trait;
-
-    CoerceUnsized,           sym::coerce_unsized,      coerce_unsized_trait,       Target::Trait;
-    DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait;
-
-    Add(Op),                 sym::add,                 add_trait,                  Target::Trait;
-    Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait;
-    Mul(Op),                 sym::mul,                 mul_trait,                  Target::Trait;
-    Div(Op),                 sym::div,                 div_trait,                  Target::Trait;
-    Rem(Op),                 sym::rem,                 rem_trait,                  Target::Trait;
-    Neg(Op),                 sym::neg,                 neg_trait,                  Target::Trait;
-    Not(Op),                 sym::not,                 not_trait,                  Target::Trait;
-    BitXor(Op),              sym::bitxor,              bitxor_trait,               Target::Trait;
-    BitAnd(Op),              sym::bitand,              bitand_trait,               Target::Trait;
-    BitOr(Op),               sym::bitor,               bitor_trait,                Target::Trait;
-    Shl(Op),                 sym::shl,                 shl_trait,                  Target::Trait;
-    Shr(Op),                 sym::shr,                 shr_trait,                  Target::Trait;
-    AddAssign(Op),           sym::add_assign,          add_assign_trait,           Target::Trait;
-    SubAssign(Op),           sym::sub_assign,          sub_assign_trait,           Target::Trait;
-    MulAssign(Op),           sym::mul_assign,          mul_assign_trait,           Target::Trait;
-    DivAssign(Op),           sym::div_assign,          div_assign_trait,           Target::Trait;
-    RemAssign(Op),           sym::rem_assign,          rem_assign_trait,           Target::Trait;
-    BitXorAssign(Op),        sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait;
-    BitAndAssign(Op),        sym::bitand_assign,       bitand_assign_trait,        Target::Trait;
-    BitOrAssign(Op),         sym::bitor_assign,        bitor_assign_trait,         Target::Trait;
-    ShlAssign(Op),           sym::shl_assign,          shl_assign_trait,           Target::Trait;
-    ShrAssign(Op),           sym::shr_assign,          shr_assign_trait,           Target::Trait;
-    Index(Op),               sym::index,               index_trait,                Target::Trait;
-    IndexMut(Op),            sym::index_mut,           index_mut_trait,            Target::Trait;
-
-    UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct;
-    VaList,                  sym::va_list,             va_list,                    Target::Struct;
-
-    Deref,                   sym::deref,               deref_trait,                Target::Trait;
-    DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait;
-    DerefTarget,             sym::deref_target,        deref_target,               Target::AssocTy;
-    Receiver,                sym::receiver,            receiver_trait,             Target::Trait;
-
-    Fn,                      kw::Fn,                   fn_trait,                   Target::Trait;
-    FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait;
-    FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait;
-
-    FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy;
-
-    Future,                  sym::future_trait,        future_trait,               Target::Trait;
-    GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum;
-    Generator,               sym::generator,           gen_trait,                  Target::Trait;
-    Unpin,                   sym::unpin,               unpin_trait,                Target::Trait;
-    Pin,                     sym::pin,                 pin_type,                   Target::Struct;
-
-    PartialEq,               sym::eq,                  eq_trait,                   Target::Trait;
-    PartialOrd,              sym::partial_ord,         partial_ord_trait,          Target::Trait;
+    Discriminant,            sym::discriminant_type,   discriminant_type,          Target::AssocTy,        GenericRequirement::None;
+
+    PointeeTrait,            sym::pointee_trait,       pointee_trait,              Target::Trait,          GenericRequirement::None;
+    Metadata,                sym::metadata_type,       metadata_type,              Target::AssocTy,        GenericRequirement::None;
+    DynMetadata,             sym::dyn_metadata,        dyn_metadata,               Target::Struct,         GenericRequirement::None;
+
+    Freeze,                  sym::freeze,              freeze_trait,               Target::Trait,          GenericRequirement::Exact(0);
+
+    Drop,                    sym::drop,                drop_trait,                 Target::Trait,          GenericRequirement::None;
+
+    CoerceUnsized,           sym::coerce_unsized,      coerce_unsized_trait,       Target::Trait,          GenericRequirement::Minimum(1);
+    DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait,          GenericRequirement::Minimum(1);
+
+    Add(Op),                 sym::add,                 add_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Mul(Op),                 sym::mul,                 mul_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Div(Op),                 sym::div,                 div_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Rem(Op),                 sym::rem,                 rem_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Neg(Op),                 sym::neg,                 neg_trait,                  Target::Trait,          GenericRequirement::Exact(0);
+    Not(Op),                 sym::not,                 not_trait,                  Target::Trait,          GenericRequirement::Exact(0);
+    BitXor(Op),              sym::bitxor,              bitxor_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    BitAnd(Op),              sym::bitand,              bitand_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    BitOr(Op),               sym::bitor,               bitor_trait,                Target::Trait,          GenericRequirement::Exact(1);
+    Shl(Op),                 sym::shl,                 shl_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Shr(Op),                 sym::shr,                 shr_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    AddAssign(Op),           sym::add_assign,          add_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    SubAssign(Op),           sym::sub_assign,          sub_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    MulAssign(Op),           sym::mul_assign,          mul_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    DivAssign(Op),           sym::div_assign,          div_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    RemAssign(Op),           sym::rem_assign,          rem_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    BitXorAssign(Op),        sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
+    BitAndAssign(Op),        sym::bitand_assign,       bitand_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
+    BitOrAssign(Op),         sym::bitor_assign,        bitor_assign_trait,         Target::Trait,          GenericRequirement::Exact(1);
+    ShlAssign(Op),           sym::shl_assign,          shl_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    ShrAssign(Op),           sym::shr_assign,          shr_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    Index(Op),               sym::index,               index_trait,                Target::Trait,          GenericRequirement::Exact(1);
+    IndexMut(Op),            sym::index_mut,           index_mut_trait,            Target::Trait,          GenericRequirement::Exact(1);
+
+    UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct,         GenericRequirement::None;
+    VaList,                  sym::va_list,             va_list,                    Target::Struct,         GenericRequirement::None;
+
+    Deref,                   sym::deref,               deref_trait,                Target::Trait,          GenericRequirement::Exact(0);
+    DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait,          GenericRequirement::Exact(0);
+    DerefTarget,             sym::deref_target,        deref_target,               Target::AssocTy,        GenericRequirement::None;
+    Receiver,                sym::receiver,            receiver_trait,             Target::Trait,          GenericRequirement::None;
+
+    Fn,                      kw::Fn,                   fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
+    FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait,          GenericRequirement::Exact(1);
+
+    FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
+
+    Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
+    GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum,           GenericRequirement::None;
+    Generator,               sym::generator,           gen_trait,                  Target::Trait,          GenericRequirement::Minimum(1);
+    Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
+    Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
+
+    PartialEq,               sym::eq,                  eq_trait,                   Target::Trait,          GenericRequirement::Exact(1);
+    PartialOrd,              sym::partial_ord,         partial_ord_trait,          Target::Trait,          GenericRequirement::Exact(1);
 
     // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
     // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
@@ -275,80 +281,86 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     // in the sense that a crate is not required to have it defined to use it, but a final product
     // is required to define it somewhere. Additionally, there are restrictions on crates that use
     // a weak lang item, but do not have it defined.
-    Panic,                   sym::panic,               panic_fn,                   Target::Fn;
-    PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn;
-    PanicStr,                sym::panic_str,           panic_str,                  Target::Fn;
-    ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn;
-    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn;
-    PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct;
-    PanicLocation,           sym::panic_location,      panic_location,             Target::Struct;
-    PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn;
+    Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::None;
+    PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
+    PanicStr,                sym::panic_str,           panic_str,                  Target::Fn,             GenericRequirement::None;
+    ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
+    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::None;
+    PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct,         GenericRequirement::None;
+    PanicLocation,           sym::panic_location,      panic_location,             Target::Struct,         GenericRequirement::None;
+    PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn,             GenericRequirement::None;
     /// libstd panic entry point. Necessary for const eval to be able to catch it
-    BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn;
-    BeginPanicFmt,           sym::begin_panic_fmt,     begin_panic_fmt,            Target::Fn;
+    BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn,             GenericRequirement::None;
+    BeginPanicFmt,           sym::begin_panic_fmt,     begin_panic_fmt,            Target::Fn,             GenericRequirement::None;
 
-    ExchangeMalloc,          sym::exchange_malloc,     exchange_malloc_fn,         Target::Fn;
-    BoxFree,                 sym::box_free,            box_free_fn,                Target::Fn;
-    DropInPlace,             sym::drop_in_place,       drop_in_place_fn,           Target::Fn;
-    Oom,                     sym::oom,                 oom,                        Target::Fn;
-    AllocLayout,             sym::alloc_layout,        alloc_layout,               Target::Struct;
+    ExchangeMalloc,          sym::exchange_malloc,     exchange_malloc_fn,         Target::Fn,             GenericRequirement::None;
+    BoxFree,                 sym::box_free,            box_free_fn,                Target::Fn,             GenericRequirement::Minimum(1);
+    DropInPlace,             sym::drop_in_place,       drop_in_place_fn,           Target::Fn,             GenericRequirement::Minimum(1);
+    Oom,                     sym::oom,                 oom,                        Target::Fn,             GenericRequirement::None;
+    AllocLayout,             sym::alloc_layout,        alloc_layout,               Target::Struct,         GenericRequirement::None;
 
-    Start,                   sym::start,               start_fn,                   Target::Fn;
+    Start,                   sym::start,               start_fn,                   Target::Fn,             GenericRequirement::None;
 
-    EhPersonality,           sym::eh_personality,      eh_personality,             Target::Fn;
-    EhCatchTypeinfo,         sym::eh_catch_typeinfo,   eh_catch_typeinfo,          Target::Static;
+    EhPersonality,           sym::eh_personality,      eh_personality,             Target::Fn,             GenericRequirement::None;
+    EhCatchTypeinfo,         sym::eh_catch_typeinfo,   eh_catch_typeinfo,          Target::Static,         GenericRequirement::None;
 
-    OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct;
+    OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct,         GenericRequirement::Minimum(1);
 
-    PhantomData,             sym::phantom_data,        phantom_data,               Target::Struct;
+    PhantomData,             sym::phantom_data,        phantom_data,               Target::Struct,         GenericRequirement::Exact(1);
 
-    ManuallyDrop,            sym::manually_drop,       manually_drop,              Target::Struct;
+    ManuallyDrop,            sym::manually_drop,       manually_drop,              Target::Struct,         GenericRequirement::None;
 
-    MaybeUninit,             sym::maybe_uninit,        maybe_uninit,               Target::Union;
+    MaybeUninit,             sym::maybe_uninit,        maybe_uninit,               Target::Union,          GenericRequirement::None;
 
     /// Align offset for stride != 1; must not panic.
-    AlignOffset,             sym::align_offset,        align_offset_fn,            Target::Fn;
+    AlignOffset,             sym::align_offset,        align_offset_fn,            Target::Fn,             GenericRequirement::None;
 
-    Termination,             sym::termination,         termination,                Target::Trait;
+    Termination,             sym::termination,         termination,                Target::Trait,          GenericRequirement::None;
 
-    Try,                     sym::Try,                 try_trait,                  Target::Trait;
+    Try,                     sym::Try,                 try_trait,                  Target::Trait,          GenericRequirement::None;
 
-    SliceLen,                sym::slice_len_fn,        slice_len_fn,               Target::Method(MethodKind::Inherent);
+    SliceLen,                sym::slice_len_fn,        slice_len_fn,               Target::Method(MethodKind::Inherent), GenericRequirement::None;
 
     // Language items from AST lowering
-    TryTraitFromResidual,    sym::from_residual,       from_residual_fn,           Target::Method(MethodKind::Trait { body: false });
-    TryTraitFromOutput,      sym::from_output,         from_output_fn,             Target::Method(MethodKind::Trait { body: false });
-    TryTraitBranch,          sym::branch,              branch_fn,                  Target::Method(MethodKind::Trait { body: false });
+    TryTraitFromResidual,    sym::from_residual,       from_residual_fn,           Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+    TryTraitFromOutput,      sym::from_output,         from_output_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+    TryTraitBranch,          sym::branch,              branch_fn,                  Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+
+    PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant,        GenericRequirement::None;
+    PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant,        GenericRequirement::None;
 
-    PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant;
-    PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant;
+    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn,             GenericRequirement::None;
+    GetContext,              sym::get_context,         get_context_fn,             Target::Fn,             GenericRequirement::None;
 
-    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn;
-    GetContext,              sym::get_context,         get_context_fn,             Target::Fn;
+    FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
-    FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false });
+    FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
 
-    FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false });
+    OptionSome,              sym::Some,                option_some_variant,        Target::Variant,        GenericRequirement::None;
+    OptionNone,              sym::None,                option_none_variant,        Target::Variant,        GenericRequirement::None;
 
-    OptionSome,              sym::Some,                option_some_variant,        Target::Variant;
-    OptionNone,              sym::None,                option_none_variant,        Target::Variant;
+    ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant,        GenericRequirement::None;
+    ResultErr,               sym::Err,                 result_err_variant,         Target::Variant,        GenericRequirement::None;
 
-    ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant;
-    ResultErr,               sym::Err,                 result_err_variant,         Target::Variant;
+    ControlFlowContinue,     sym::Continue,            cf_continue_variant,        Target::Variant,        GenericRequirement::None;
+    ControlFlowBreak,        sym::Break,               cf_break_variant,           Target::Variant,        GenericRequirement::None;
 
-    ControlFlowContinue,     sym::Continue,            cf_continue_variant,        Target::Variant;
-    ControlFlowBreak,        sym::Break,               cf_break_variant,           Target::Variant;
+    IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+    IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
 
-    IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false });
-    IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false});
+    PinNewUnchecked,         sym::new_unchecked,       new_unchecked_fn,           Target::Method(MethodKind::Inherent), GenericRequirement::None;
 
-    PinNewUnchecked,         sym::new_unchecked,       new_unchecked_fn,           Target::Method(MethodKind::Inherent);
+    RangeFrom,               sym::RangeFrom,           range_from_struct,          Target::Struct,         GenericRequirement::None;
+    RangeFull,               sym::RangeFull,           range_full_struct,          Target::Struct,         GenericRequirement::None;
+    RangeInclusiveStruct,    sym::RangeInclusive,      range_inclusive_struct,     Target::Struct,         GenericRequirement::None;
+    RangeInclusiveNew,       sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+    Range,                   sym::Range,               range_struct,               Target::Struct,         GenericRequirement::None;
+    RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct,         GenericRequirement::None;
+    RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct,         GenericRequirement::None;
+}
 
-    RangeFrom,               sym::RangeFrom,           range_from_struct,          Target::Struct;
-    RangeFull,               sym::RangeFull,           range_full_struct,          Target::Struct;
-    RangeInclusiveStruct,    sym::RangeInclusive,      range_inclusive_struct,     Target::Struct;
-    RangeInclusiveNew,       sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
-    Range,                   sym::Range,               range_struct,               Target::Struct;
-    RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
-    RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct;
+pub enum GenericRequirement {
+    None,
+    Minimum(usize),
+    Exact(usize),
 }
index 560607528330bbd04c187b67b8988567fd02dc6b..422a1064874c5c879d1f5de4f18b6b51671a5f5c 100644 (file)
@@ -1,8 +1,8 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 
 use crate::hir::{
-    BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, MacroDef, Mod,
-    TraitItem, TraitItemId, Ty, VisibilityKind,
+    BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem,
+    TraitItemId, Ty, VisibilityKind,
 };
 use crate::hir_id::{HirId, ItemLocalId};
 use rustc_span::def_id::DefPathHash;
@@ -190,16 +190,3 @@ fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         });
     }
 }
-
-impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for MacroDef<'_> {
-    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
-        let MacroDef { ident, def_id: _, ref ast, ref vis, span } = *self;
-
-        hcx.hash_hir_item_like(|hcx| {
-            ident.name.hash_stable(hcx, hasher);
-            ast.hash_stable(hcx, hasher);
-            vis.hash_stable(hcx, hasher);
-            span.hash_stable(hcx, hasher);
-        });
-    }
-}
index 473477bf22da26b91cbdc7758c364146135046b9..29c948fe31845745a81074eabe2a0192fd01347b 100644 (file)
@@ -111,6 +111,7 @@ pub fn from_item(item: &Item<'_>) -> Target {
             ItemKind::Static(..) => Target::Static,
             ItemKind::Const(..) => Target::Const,
             ItemKind::Fn(..) => Target::Fn,
+            ItemKind::Macro(..) => Target::MacroDef,
             ItemKind::Mod(..) => Target::Mod,
             ItemKind::ForeignMod { .. } => Target::ForeignMod,
             ItemKind::GlobalAsm(..) => Target::GlobalAsm,
index 9c286ad5ccfe911c417f4c614b3195a02c4296ed..42e51f4bb48c74e76de9980647dd249290e57ec2 100644 (file)
@@ -120,7 +120,6 @@ pub fn print_node(&mut self, node: Node<'_>) {
             // printing.
             Node::Ctor(..) => panic!("cannot print isolated Ctor"),
             Node::Local(a) => self.print_local_decl(&a),
-            Node::MacroDef(_) => panic!("cannot print MacroDef"),
             Node::Crate(..) => panic!("cannot print Crate"),
         }
     }
@@ -642,6 +641,11 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.end(); // need to close a box
                 self.ann.nested(self, Nested::Body(body));
             }
+            hir::ItemKind::Macro(ref macro_def) => {
+                self.print_mac_def(macro_def, &item.ident, &item.span, |state| {
+                    state.print_visibility(&item.vis)
+                });
+            }
             hir::ItemKind::Mod(ref _mod) => {
                 self.head(visibility_qualified(&item.vis, "mod"));
                 self.print_ident(item.ident);
index c4dc0fbadc813d885f4ff9b775d9fa060cc81319..c190391d2118098e18bbd0df6b5450f75ae10f7e 100644 (file)
@@ -142,7 +142,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
         krate.visit_all_item_likes(&mut dirty_clean_visitor);
 
         let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
-        intravisit::walk_crate(&mut all_attrs, krate);
+        tcx.hir().walk_attributes(&mut all_attrs);
 
         // Note that we cannot use the existing "unused attribute"-infrastructure
         // here, since that is running before codegen. This is also the reason why
index df777502c44a4a6d922e4a78f9084439339df920..aeb3f9970ab9e6a0cda3cb926d1dc54117c30818 100644 (file)
 pub const WORD_BYTES: usize = mem::size_of::<Word>();
 pub const WORD_BITS: usize = WORD_BYTES * 8;
 
+pub trait BitRelations<Rhs> {
+    fn union(&mut self, other: &Rhs) -> bool;
+    fn subtract(&mut self, other: &Rhs) -> bool;
+    fn intersect(&mut self, other: &Rhs) -> bool;
+}
+
+macro_rules! bit_relations_inherent_impls {
+    () => {
+        /// Sets `self = self | other` and returns `true` if `self` changed
+        /// (i.e., if new bits were added).
+        pub fn union<Rhs>(&mut self, other: &Rhs) -> bool
+        where
+            Self: BitRelations<Rhs>,
+        {
+            <Self as BitRelations<Rhs>>::union(self, other)
+        }
+
+        /// Sets `self = self - other` and returns `true` if `self` changed.
+        /// (i.e., if any bits were removed).
+        pub fn subtract<Rhs>(&mut self, other: &Rhs) -> bool
+        where
+            Self: BitRelations<Rhs>,
+        {
+            <Self as BitRelations<Rhs>>::subtract(self, other)
+        }
+
+        /// Sets `self = self & other` and return `true` if `self` changed.
+        /// (i.e., if any bits were removed).
+        pub fn intersect<Rhs>(&mut self, other: &Rhs) -> bool
+        where
+            Self: BitRelations<Rhs>,
+        {
+            <Self as BitRelations<Rhs>>::intersect(self, other)
+        }
+    };
+}
+
 /// A fixed-size bitset type with a dense representation.
 ///
 /// NOTE: Use [`GrowableBitSet`] if you need support for resizing after creation.
@@ -134,25 +171,6 @@ pub fn remove(&mut self, elem: T) -> bool {
         new_word != word
     }
 
-    /// Sets `self = self | other` and returns `true` if `self` changed
-    /// (i.e., if new bits were added).
-    pub fn union(&mut self, other: &impl UnionIntoBitSet<T>) -> bool {
-        other.union_into(self)
-    }
-
-    /// Sets `self = self - other` and returns `true` if `self` changed.
-    /// (i.e., if any bits were removed).
-    pub fn subtract(&mut self, other: &impl SubtractFromBitSet<T>) -> bool {
-        other.subtract_from(self)
-    }
-
-    /// Sets `self = self & other` and return `true` if `self` changed.
-    /// (i.e., if any bits were removed).
-    pub fn intersect(&mut self, other: &BitSet<T>) -> bool {
-        assert_eq!(self.domain_size, other.domain_size);
-        bitwise(&mut self.words, &other.words, |a, b| a & b)
-    }
-
     /// Gets a slice of the underlying words.
     pub fn words(&self) -> &[Word] {
         &self.words
@@ -208,33 +226,208 @@ fn reverse_union_sparse(&mut self, sparse: &SparseBitSet<T>) -> bool {
 
         not_already
     }
+
+    bit_relations_inherent_impls! {}
 }
 
-/// This is implemented by all the bitsets so that BitSet::union() can be
-/// passed any type of bitset.
-pub trait UnionIntoBitSet<T: Idx> {
-    // Performs `other = other | self`.
-    fn union_into(&self, other: &mut BitSet<T>) -> bool;
+// dense REL dense
+impl<T: Idx> BitRelations<BitSet<T>> for BitSet<T> {
+    fn union(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size);
+        bitwise(&mut self.words, &other.words, |a, b| a | b)
+    }
+
+    fn subtract(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size);
+        bitwise(&mut self.words, &other.words, |a, b| a & !b)
+    }
+
+    fn intersect(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size);
+        bitwise(&mut self.words, &other.words, |a, b| a & b)
+    }
 }
 
-/// This is implemented by all the bitsets so that BitSet::subtract() can be
-/// passed any type of bitset.
-pub trait SubtractFromBitSet<T: Idx> {
-    // Performs `other = other - self`.
-    fn subtract_from(&self, other: &mut BitSet<T>) -> bool;
+// Applies a function to mutate a bitset, and returns true if any
+// of the applications return true
+fn sequential_update<T: Idx>(
+    mut self_update: impl FnMut(T) -> bool,
+    it: impl Iterator<Item = T>,
+) -> bool {
+    let mut changed = false;
+    for elem in it {
+        changed |= self_update(elem);
+    }
+    changed
 }
 
-impl<T: Idx> UnionIntoBitSet<T> for BitSet<T> {
-    fn union_into(&self, other: &mut BitSet<T>) -> bool {
-        assert_eq!(self.domain_size, other.domain_size);
-        bitwise(&mut other.words, &self.words, |a, b| a | b)
+// Optimization of intersection for SparseBitSet that's generic
+// over the RHS
+fn sparse_intersect<T: Idx>(
+    set: &mut SparseBitSet<T>,
+    other_contains: impl Fn(&T) -> bool,
+) -> bool {
+    let size = set.elems.len();
+    set.elems.retain(|elem| other_contains(elem));
+    set.elems.len() != size
+}
+
+// Optimization of dense/sparse intersection. The resulting set is
+// guaranteed to be at most the size of the sparse set, and hence can be
+// represented as a sparse set. Therefore the sparse set is copied and filtered,
+// then returned as the new set.
+fn dense_sparse_intersect<T: Idx>(
+    dense: &BitSet<T>,
+    sparse: &SparseBitSet<T>,
+) -> (SparseBitSet<T>, bool) {
+    let mut sparse_copy = sparse.clone();
+    sparse_intersect(&mut sparse_copy, |el| dense.contains(*el));
+    let n = sparse_copy.len();
+    (sparse_copy, n != dense.count())
+}
+
+// hybrid REL dense
+impl<T: Idx> BitRelations<BitSet<T>> for HybridBitSet<T> {
+    fn union(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size);
+        match self {
+            HybridBitSet::Sparse(sparse) => {
+                // `self` is sparse and `other` is dense. To
+                // merge them, we have two available strategies:
+                // * Densify `self` then merge other
+                // * Clone other then integrate bits from `self`
+                // The second strategy requires dedicated method
+                // since the usual `union` returns the wrong
+                // result. In the dedicated case the computation
+                // is slightly faster if the bits of the sparse
+                // bitset map to only few words of the dense
+                // representation, i.e. indices are near each
+                // other.
+                //
+                // Benchmarking seems to suggest that the second
+                // option is worth it.
+                let mut new_dense = other.clone();
+                let changed = new_dense.reverse_union_sparse(sparse);
+                *self = HybridBitSet::Dense(new_dense);
+                changed
+            }
+
+            HybridBitSet::Dense(dense) => dense.union(other),
+        }
+    }
+
+    fn subtract(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size);
+        match self {
+            HybridBitSet::Sparse(sparse) => {
+                sequential_update(|elem| sparse.remove(elem), other.iter())
+            }
+            HybridBitSet::Dense(dense) => dense.subtract(other),
+        }
+    }
+
+    fn intersect(&mut self, other: &BitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size);
+        match self {
+            HybridBitSet::Sparse(sparse) => sparse_intersect(sparse, |elem| other.contains(*elem)),
+            HybridBitSet::Dense(dense) => dense.intersect(other),
+        }
     }
 }
 
-impl<T: Idx> SubtractFromBitSet<T> for BitSet<T> {
-    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
-        assert_eq!(self.domain_size, other.domain_size);
-        bitwise(&mut other.words, &self.words, |a, b| a & !b)
+// dense REL hybrid
+impl<T: Idx> BitRelations<HybridBitSet<T>> for BitSet<T> {
+    fn union(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size());
+        match other {
+            HybridBitSet::Sparse(sparse) => {
+                sequential_update(|elem| self.insert(elem), sparse.iter().cloned())
+            }
+            HybridBitSet::Dense(dense) => self.union(dense),
+        }
+    }
+
+    fn subtract(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size());
+        match other {
+            HybridBitSet::Sparse(sparse) => {
+                sequential_update(|elem| self.remove(elem), sparse.iter().cloned())
+            }
+            HybridBitSet::Dense(dense) => self.subtract(dense),
+        }
+    }
+
+    fn intersect(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size, other.domain_size());
+        match other {
+            HybridBitSet::Sparse(sparse) => {
+                let (updated, changed) = dense_sparse_intersect(self, sparse);
+
+                // We can't directly assign the SparseBitSet to the BitSet, and
+                // doing `*self = updated.to_dense()` would cause a drop / reallocation. Instead,
+                // the BitSet is cleared and `updated` is copied into `self`.
+                self.clear();
+                for elem in updated.iter() {
+                    self.insert(*elem);
+                }
+                changed
+            }
+            HybridBitSet::Dense(dense) => self.intersect(dense),
+        }
+    }
+}
+
+// hybrid REL hybrid
+impl<T: Idx> BitRelations<HybridBitSet<T>> for HybridBitSet<T> {
+    fn union(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size());
+        match self {
+            HybridBitSet::Sparse(_) => {
+                match other {
+                    HybridBitSet::Sparse(other_sparse) => {
+                        // Both sets are sparse. Add the elements in
+                        // `other_sparse` to `self` one at a time. This
+                        // may or may not cause `self` to be densified.
+                        let mut changed = false;
+                        for elem in other_sparse.iter() {
+                            changed |= self.insert(*elem);
+                        }
+                        changed
+                    }
+
+                    HybridBitSet::Dense(other_dense) => self.union(other_dense),
+                }
+            }
+
+            HybridBitSet::Dense(self_dense) => self_dense.union(other),
+        }
+    }
+
+    fn subtract(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size());
+        match self {
+            HybridBitSet::Sparse(self_sparse) => {
+                sequential_update(|elem| self_sparse.remove(elem), other.iter())
+            }
+            HybridBitSet::Dense(self_dense) => self_dense.subtract(other),
+        }
+    }
+
+    fn intersect(&mut self, other: &HybridBitSet<T>) -> bool {
+        assert_eq!(self.domain_size(), other.domain_size());
+        match self {
+            HybridBitSet::Sparse(self_sparse) => {
+                sparse_intersect(self_sparse, |elem| other.contains(*elem))
+            }
+            HybridBitSet::Dense(self_dense) => match other {
+                HybridBitSet::Sparse(other_sparse) => {
+                    let (updated, changed) = dense_sparse_intersect(self_dense, other_sparse);
+                    *self = HybridBitSet::Sparse(updated);
+                    changed
+                }
+                HybridBitSet::Dense(other_dense) => self_dense.intersect(other_dense),
+            },
+        }
     }
 }
 
@@ -441,28 +634,8 @@ fn to_dense(&self) -> BitSet<T> {
     fn iter(&self) -> slice::Iter<'_, T> {
         self.elems.iter()
     }
-}
 
-impl<T: Idx> UnionIntoBitSet<T> for SparseBitSet<T> {
-    fn union_into(&self, other: &mut BitSet<T>) -> bool {
-        assert_eq!(self.domain_size, other.domain_size);
-        let mut changed = false;
-        for elem in self.iter() {
-            changed |= other.insert(*elem);
-        }
-        changed
-    }
-}
-
-impl<T: Idx> SubtractFromBitSet<T> for SparseBitSet<T> {
-    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
-        assert_eq!(self.domain_size, other.domain_size);
-        let mut changed = false;
-        for elem in self.iter() {
-            changed |= other.remove(*elem);
-        }
-        changed
-    }
+    bit_relations_inherent_impls! {}
 }
 
 /// A fixed-size bitset type with a hybrid representation: sparse when there
@@ -579,48 +752,6 @@ pub fn remove(&mut self, elem: T) -> bool {
         }
     }
 
-    pub fn union(&mut self, other: &HybridBitSet<T>) -> bool {
-        match self {
-            HybridBitSet::Sparse(self_sparse) => {
-                match other {
-                    HybridBitSet::Sparse(other_sparse) => {
-                        // Both sets are sparse. Add the elements in
-                        // `other_sparse` to `self` one at a time. This
-                        // may or may not cause `self` to be densified.
-                        assert_eq!(self.domain_size(), other.domain_size());
-                        let mut changed = false;
-                        for elem in other_sparse.iter() {
-                            changed |= self.insert(*elem);
-                        }
-                        changed
-                    }
-                    HybridBitSet::Dense(other_dense) => {
-                        // `self` is sparse and `other` is dense. To
-                        // merge them, we have two available strategies:
-                        // * Densify `self` then merge other
-                        // * Clone other then integrate bits from `self`
-                        // The second strategy requires dedicated method
-                        // since the usual `union` returns the wrong
-                        // result. In the dedicated case the computation
-                        // is slightly faster if the bits of the sparse
-                        // bitset map to only few words of the dense
-                        // representation, i.e. indices are near each
-                        // other.
-                        //
-                        // Benchmarking seems to suggest that the second
-                        // option is worth it.
-                        let mut new_dense = other_dense.clone();
-                        let changed = new_dense.reverse_union_sparse(self_sparse);
-                        *self = HybridBitSet::Dense(new_dense);
-                        changed
-                    }
-                }
-            }
-
-            HybridBitSet::Dense(self_dense) => self_dense.union(other),
-        }
-    }
-
     /// Converts to a dense set, consuming itself in the process.
     pub fn to_dense(self) -> BitSet<T> {
         match self {
@@ -635,24 +766,8 @@ pub fn iter(&self) -> HybridIter<'_, T> {
             HybridBitSet::Dense(dense) => HybridIter::Dense(dense.iter()),
         }
     }
-}
-
-impl<T: Idx> UnionIntoBitSet<T> for HybridBitSet<T> {
-    fn union_into(&self, other: &mut BitSet<T>) -> bool {
-        match self {
-            HybridBitSet::Sparse(sparse) => sparse.union_into(other),
-            HybridBitSet::Dense(dense) => dense.union_into(other),
-        }
-    }
-}
 
-impl<T: Idx> SubtractFromBitSet<T> for HybridBitSet<T> {
-    fn subtract_from(&self, other: &mut BitSet<T>) -> bool {
-        match self {
-            HybridBitSet::Sparse(sparse) => sparse.subtract_from(other),
-            HybridBitSet::Dense(dense) => dense.subtract_from(other),
-        }
-    }
+    bit_relations_inherent_impls! {}
 }
 
 pub enum HybridIter<'a, T: Idx> {
@@ -974,6 +1089,26 @@ pub fn insert(&mut self, row: R, column: C) -> bool {
         self.ensure_row(row).insert(column)
     }
 
+    /// Sets the cell at `(row, column)` to false. Put another way, delete
+    /// `column` from the bitset for `row`. Has no effect if `row` does not
+    /// exist.
+    ///
+    /// Returns `true` if this changed the matrix.
+    pub fn remove(&mut self, row: R, column: C) -> bool {
+        match self.rows.get_mut(row) {
+            Some(Some(row)) => row.remove(column),
+            _ => false,
+        }
+    }
+
+    /// Sets all columns at `row` to false. Has no effect if `row` does
+    /// not exist.
+    pub fn clear(&mut self, row: R) {
+        if let Some(Some(row)) = self.rows.get_mut(row) {
+            row.clear();
+        }
+    }
+
     /// Do the bits from `row` contain `column`? Put another way, is
     /// the matrix cell at `(row, column)` true?  Put yet another way,
     /// if the matrix represents (transitive) reachability, can
@@ -1002,11 +1137,6 @@ pub fn union_rows(&mut self, read: R, write: R) -> bool {
         }
     }
 
-    /// Union a row, `from`, into the `into` row.
-    pub fn union_into_row(&mut self, into: R, from: &HybridBitSet<C>) -> bool {
-        self.ensure_row(into).union(from)
-    }
-
     /// Insert all bits in the given row.
     pub fn insert_all_into_row(&mut self, row: R) {
         self.ensure_row(row).insert_all();
@@ -1025,6 +1155,45 @@ pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
     pub fn row(&self, row: R) -> Option<&HybridBitSet<C>> {
         if let Some(Some(row)) = self.rows.get(row) { Some(row) } else { None }
     }
+
+    /// Interescts `row` with `set`. `set` can be either `BitSet` or
+    /// `HybridBitSet`. Has no effect if `row` does not exist.
+    ///
+    /// Returns true if the row was changed.
+    pub fn intersect_row<Set>(&mut self, row: R, set: &Set) -> bool
+    where
+        HybridBitSet<C>: BitRelations<Set>,
+    {
+        match self.rows.get_mut(row) {
+            Some(Some(row)) => row.intersect(set),
+            _ => false,
+        }
+    }
+
+    /// Subtracts `set from `row`. `set` can be either `BitSet` or
+    /// `HybridBitSet`. Has no effect if `row` does not exist.
+    ///
+    /// Returns true if the row was changed.
+    pub fn subtract_row<Set>(&mut self, row: R, set: &Set) -> bool
+    where
+        HybridBitSet<C>: BitRelations<Set>,
+    {
+        match self.rows.get_mut(row) {
+            Some(Some(row)) => row.subtract(set),
+            _ => false,
+        }
+    }
+
+    /// Unions `row` with `set`. `set` can be either `BitSet` or
+    /// `HybridBitSet`.
+    ///
+    /// Returns true if the row was changed.
+    pub fn union_row<Set>(&mut self, row: R, set: &Set) -> bool
+    where
+        HybridBitSet<C>: BitRelations<Set>,
+    {
+        self.ensure_row(row).union(set)
+    }
 }
 
 #[inline]
index c11b98e77aa58ac5aac4c548dc58c0214dd3610f..aebc6d0ddd84ca9e5cd1efa4d2376e6236cffe4f 100644 (file)
@@ -104,18 +104,40 @@ fn hybrid_bitset() {
     assert!(dense10.superset(&dense10)); // dense + dense (self)
     assert!(dense256.superset(&dense10)); // dense + dense
 
-    let mut hybrid = sparse038;
+    let mut hybrid = sparse038.clone();
     assert!(!sparse01358.union(&hybrid)); // no change
     assert!(hybrid.union(&sparse01358));
     assert!(hybrid.superset(&sparse01358) && sparse01358.superset(&hybrid));
-    assert!(!dense10.union(&sparse01358));
     assert!(!dense256.union(&dense10));
-    let mut dense = dense10;
+
+    // dense / sparse where dense superset sparse
+    assert!(!dense10.clone().union(&sparse01358));
+    assert!(sparse01358.clone().union(&dense10));
+    assert!(dense10.clone().intersect(&sparse01358));
+    assert!(!sparse01358.clone().intersect(&dense10));
+    assert!(dense10.clone().subtract(&sparse01358));
+    assert!(sparse01358.clone().subtract(&dense10));
+
+    // dense / sparse where sparse superset dense
+    let dense038 = sparse038.to_dense();
+    assert!(!sparse01358.clone().union(&dense038));
+    assert!(dense038.clone().union(&sparse01358));
+    assert!(sparse01358.clone().intersect(&dense038));
+    assert!(!dense038.clone().intersect(&sparse01358));
+    assert!(sparse01358.clone().subtract(&dense038));
+    assert!(dense038.clone().subtract(&sparse01358));
+
+    let mut dense = dense10.clone();
     assert!(dense.union(&dense256));
     assert!(dense.superset(&dense256) && dense256.superset(&dense));
     assert!(hybrid.union(&dense256));
     assert!(hybrid.superset(&dense256) && dense256.superset(&hybrid));
 
+    assert!(!dense10.clone().intersect(&dense256));
+    assert!(dense256.clone().intersect(&dense10));
+    assert!(dense10.clone().subtract(&dense256));
+    assert!(dense256.clone().subtract(&dense10));
+
     assert_eq!(dense256.iter().count(), 256);
     let mut dense0 = dense256;
     for i in 0..256 {
@@ -282,6 +304,72 @@ fn sparse_matrix_iter() {
     assert!(iter.next().is_none());
 }
 
+#[test]
+fn sparse_matrix_operations() {
+    let mut matrix: SparseBitMatrix<usize, usize> = SparseBitMatrix::new(100);
+    matrix.insert(3, 22);
+    matrix.insert(3, 75);
+    matrix.insert(2, 99);
+    matrix.insert(4, 0);
+
+    let mut disjoint: HybridBitSet<usize> = HybridBitSet::new_empty(100);
+    disjoint.insert(33);
+
+    let mut superset = HybridBitSet::new_empty(100);
+    superset.insert(22);
+    superset.insert(75);
+    superset.insert(33);
+
+    let mut subset = HybridBitSet::new_empty(100);
+    subset.insert(22);
+
+    // SparseBitMatrix::remove
+    {
+        let mut matrix = matrix.clone();
+        matrix.remove(3, 22);
+        assert!(!matrix.row(3).unwrap().contains(22));
+        matrix.remove(0, 0);
+        assert!(matrix.row(0).is_none());
+    }
+
+    // SparseBitMatrix::clear
+    {
+        let mut matrix = matrix.clone();
+        matrix.clear(3);
+        assert!(!matrix.row(3).unwrap().contains(75));
+        matrix.clear(0);
+        assert!(matrix.row(0).is_none());
+    }
+
+    // SparseBitMatrix::intersect_row
+    {
+        let mut matrix = matrix.clone();
+        assert!(!matrix.intersect_row(3, &superset));
+        assert!(matrix.intersect_row(3, &subset));
+        matrix.intersect_row(0, &disjoint);
+        assert!(matrix.row(0).is_none());
+    }
+
+    // SparseBitMatrix::subtract_row
+    {
+        let mut matrix = matrix.clone();
+        assert!(!matrix.subtract_row(3, &disjoint));
+        assert!(matrix.subtract_row(3, &subset));
+        assert!(matrix.subtract_row(3, &superset));
+        matrix.intersect_row(0, &disjoint);
+        assert!(matrix.row(0).is_none());
+    }
+
+    // SparseBitMatrix::union_row
+    {
+        let mut matrix = matrix.clone();
+        assert!(!matrix.union_row(3, &subset));
+        assert!(matrix.union_row(3, &disjoint));
+        matrix.union_row(0, &disjoint);
+        assert!(matrix.row(0).is_some());
+    }
+}
+
 /// Merge dense hybrid set into empty sparse hybrid set.
 #[bench]
 fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) {
index 448dd6623482cf67f6fbddc93c5921a64b4d4d87..934ada9932e71ad91d9b737b0ed38ff145696d17 100644 (file)
@@ -470,7 +470,7 @@ fn canonicalize<V>(
     {
         let needs_canonical_flags = if canonicalize_region_mode.any() {
             TypeFlags::NEEDS_INFER |
-            TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
+            TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_POTENTIAL_FREE_REGIONS`
             TypeFlags::HAS_TY_PLACEHOLDER |
             TypeFlags::HAS_CT_PLACEHOLDER
         } else {
index c3c28d70081512550f398aacac7337d78888947d..6a97a6c43c11e564ef12427fc7aa15225aafc1e4 100644 (file)
@@ -678,7 +678,7 @@ fn push_outlives(
     fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {
         span_bug!(
             self.cause.span(self.infcx.tcx),
-            "lazy_normalization_consts: unreachable `const_equate`"
+            "generic_const_exprs: unreachable `const_equate`"
         );
     }
 
index 01d84e287bc9fbf788446269c646562b3cf8086a..a0ee212bed0cd5df3d1360950b38e3413296169e 100644 (file)
@@ -129,6 +129,8 @@ pub fn super_combine_consts<R>(
     where
         R: ConstEquateRelation<'tcx>,
     {
+        let a = self.tcx.expose_default_const_substs(a);
+        let b = self.tcx.expose_default_const_substs(b);
         debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
         if a == b {
             return Ok(a);
@@ -200,7 +202,7 @@ pub fn super_combine_consts<R>(
     /// A good example of this is the following:
     ///
     /// ```rust
-    /// #![feature(const_generics)]
+    /// #![feature(generic_const_exprs)]
     ///
     /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
     ///     todo!()
@@ -742,10 +744,9 @@ fn consts(
                     }
                 }
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
-                if self.tcx().lazy_normalization() =>
-            {
-                assert_eq!(promoted, None);
+            ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
+                assert_eq!(uv.promoted, None);
+                let substs = uv.substs(self.tcx());
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
@@ -754,7 +755,7 @@ fn consts(
                 )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
@@ -976,10 +977,9 @@ fn consts(
                     }
                 }
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
-                if self.tcx().lazy_normalization() =>
-            {
-                assert_eq!(promoted, None);
+            ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
+                assert_eq!(uv.promoted, None);
+                let substs = uv.substs(self.tcx());
                 let substs = self.relate_with_variance(
                     ty::Variance::Invariant,
                     ty::VarianceDiagInfo::default(),
@@ -988,7 +988,7 @@ fn consts(
                 )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
-                    val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+                    val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
                 }))
             }
             _ => relate::super_relate_consts(self, c, c),
index 4830158c15afc6463bf5fb2dcd7ee67e01218654..32150c7f4c615dfc18f5bd70481fc7ba5ba24dbd 100644 (file)
@@ -781,6 +781,10 @@ fn note_error_origin(
                     );
                 }
             }
+            ObligationCauseCode::LetElse => {
+                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
+                err.help("...or use `match` instead of `let...else`");
+            }
             _ => (),
         }
     }
@@ -1537,6 +1541,10 @@ fn add_labels_for_types(
         }
 
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
+            fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                Some(self.tcx)
+            }
+
             fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
                     let span = self.tcx.def_span(def_id);
@@ -1622,14 +1630,11 @@ enum Mismatch<'a> {
                 (TypeError::Sorts(values), extra) => {
                     let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
                         (true, ty::Opaque(def_id, _)) => {
-                            let pos = self
-                                .tcx
-                                .sess
-                                .source_map()
-                                .lookup_char_pos(self.tcx.def_span(*def_id).lo());
+                            let sm = self.tcx.sess.source_map();
+                            let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
                             format!(
                                 " (opaque type at <{}:{}:{}>)",
-                                pos.file.name.prefer_local(),
+                                sm.filename_for_diagnostics(&pos.file.name),
                                 pos.line,
                                 pos.col.to_usize() + 1,
                             )
@@ -2588,6 +2593,7 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
             }
             IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
             IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
+            LetElse => Error0308("`else` clause of `let...else` does not diverge"),
             MainFunctionType => Error0580("`main` function has wrong type"),
             StartFunctionType => Error0308("`#[start]` function has wrong type"),
             IntrinsicType => Error0308("intrinsic has wrong type"),
index c2025f3fe4da27498f64b7bef5c8fbf12b7a2f1b..e00003face9ced40b6f7d3e13367b05b4e7d68cc 100644 (file)
@@ -51,7 +51,7 @@ fn node_type_opt(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
 
     fn node_ty_contains_target(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
         self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| {
-            ty.walk().any(|inner| {
+            ty.walk(self.infcx.tcx).any(|inner| {
                 inner == self.target
                     || match (inner.unpack(), self.target.unpack()) {
                         (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
index fde4ec05ffc867f74ec0aeced86aa748bc26d07e..81059fbcb10511265061f17010f237c9bdbf9229 100644 (file)
@@ -9,7 +9,9 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
 use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
-use rustc_middle::ty::{self, AssocItemContainer, RegionKind, Ty, TypeFoldable, TypeVisitor};
+use rustc_middle::ty::{
+    self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
+};
 use rustc_span::symbol::Ident;
 use rustc_span::{MultiSpan, Span};
 
@@ -476,8 +478,14 @@ fn suggest_constrain_dyn_trait_in_impl(
 /// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
 pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
 
-impl TypeVisitor<'_> for TraitObjectVisitor {
-    fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
+impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        // The default anon const substs cannot include
+        // trait objects, so we don't have to bother looking.
+        None
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
             ty::Dynamic(preds, RegionKind::ReStatic) => {
                 if let Some(def_id) = preds.principal_def_id() {
index 4af1bdf97a773f7e9796b857d02ce31ff6f24b32..c40e409891bc25cb76a7612fbab231493c67de98 100644 (file)
@@ -146,7 +146,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_infer() && !t.has_erasable_regions() {
+        if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
             return t;
         }
 
index 9013bea749a299fb559bc0951dcc2dace2647ae0..bc98a3aa3f95e563d1982137b0ac0e7b4e65d71a 100644 (file)
@@ -675,13 +675,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// canonicalizing the consts.
     pub fn try_unify_abstract_consts(
         &self,
-        a: ty::Unevaluated<'tcx>,
-        b: ty::Unevaluated<'tcx>,
+        a: ty::Unevaluated<'tcx, ()>,
+        b: ty::Unevaluated<'tcx, ()>,
     ) -> bool {
-        let canonical = self.canonicalize_query(
-            ((a.def, a.substs), (b.def, b.substs)),
-            &mut OriginalQueryValues::default(),
-        );
+        let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default());
         debug!("canonical consts: {:?}", &canonical.value);
 
         self.tcx.try_unify_abstract_consts(canonical.value)
@@ -1592,16 +1589,16 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
     pub fn const_eval_resolve(
         &self,
         param_env: ty::ParamEnv<'tcx>,
-        ty::Unevaluated { def, substs, promoted }: ty::Unevaluated<'tcx>,
+        unevaluated: ty::Unevaluated<'tcx>,
         span: Option<Span>,
     ) -> EvalToConstValueResult<'tcx> {
         let mut original_values = OriginalQueryValues::default();
-        let canonical = self.canonicalize_query((param_env, substs), &mut original_values);
+        let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values);
 
-        let (param_env, substs) = canonical.value;
+        let (param_env, unevaluated) = canonical.value;
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
-        self.tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, span)
+        self.tcx.const_eval_resolve(param_env, unevaluated, span)
     }
 
     /// If `typ` is a type variable of some kind, resolve it one level
index 042e6159aff8b220b4abe97ad372f1af027cf49f..c211d8e94a68b1b05b2ba0f8bedb276c57d0f2ae 100644 (file)
@@ -202,6 +202,7 @@ fn create_scope(
         };
 
         value.skip_binder().visit_with(&mut ScopeInstantiator {
+            tcx: self.infcx.tcx,
             next_region: &mut next_region,
             target_index: ty::INNERMOST,
             bound_region_scope: &mut scope,
@@ -757,6 +758,7 @@ fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Con
 /// `for<..`>.  For each of those, it creates an entry in
 /// `bound_region_scope`.
 struct ScopeInstantiator<'me, 'tcx> {
+    tcx: TyCtxt<'tcx>,
     next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
     // The debruijn index of the scope we are instantiating.
     target_index: ty::DebruijnIndex,
@@ -764,6 +766,10 @@ struct ScopeInstantiator<'me, 'tcx> {
 }
 
 impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &ty::Binder<'tcx, T>,
index f69212c599b6258dbb4964098c7a15749aea9e32..dba73251b4f0d44e9e8d68e3333c6f44181e38f5 100644 (file)
@@ -189,7 +189,7 @@ fn recursive_bound(
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
         let mut bounds = parent
-            .walk_shallow(visited)
+            .walk_shallow(self.tcx, visited)
             .filter_map(|child| match child.unpack() {
                 GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
                 GenericArgKind::Lifetime(lt) => {
index 48b8ee17594e3bd10708b88b8978a2417fb75572..4b08c2eb9c19eee7d3bf9cc9327553a17d82518c 100644 (file)
@@ -126,6 +126,11 @@ pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
 
 impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
     type BreakTy = (Ty<'tcx>, Option<Span>);
+
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.infcx.tcx)
+    }
+
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         let t = self.infcx.shallow_resolve(t);
         if t.has_infer_types() {
index 0ac4b6b25bbfe54804ae045cd29dfdb8ff922f65..d0bd508bc257f2dfd4fd63b71bdd0e65c669a7f2 100644 (file)
@@ -104,11 +104,5 @@ pub fn report_object_safety_error(
          to be resolvable dynamically; for more information visit \
          <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
     );
-
-    if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) {
-        // Avoid emitting error caused by non-existing method (#58734)
-        err.cancel();
-    }
-
     err
 }
index 5dc57f6023b767764ff7ea644b4e20c6c56e93be..1d542db9b69c3eef068d2f40b1707f3038a0f5d9 100644 (file)
@@ -324,7 +324,7 @@ pub fn configure_and_expand(
         };
 
         let extern_mod_loaded = |ident: Ident, attrs, items, span| {
-            let krate = ast::Crate { attrs, items, span, proc_macros: vec![] };
+            let krate = ast::Crate { attrs, items, span };
             pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str());
             (krate.attrs, krate.items)
         };
@@ -464,10 +464,6 @@ pub fn lower_to_hir<'res, 'tcx>(
         arena,
     );
 
-    if sess.opts.debugging_opts.hir_stats {
-        hir_stats::print_hir_stats(&hir_crate);
-    }
-
     sess.time("early_lint_checks", || {
         rustc_lint::check_ast_crate(
             sess,
index b896143400698745985faaabf8bda2b2109ebeb9..afab919bc3c2cff582ac90614c5f6d3a7bc9fc51 100644 (file)
@@ -743,6 +743,7 @@ macro_rules! tracked {
     tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
+    tracked!(partially_uninit_const_threshold, Some(123));
     tracked!(plt, Some(true));
     tracked!(polonius, true);
     tracked!(precise_enum_drop_elaboration, false);
index 6b64614363f188909a62e56f08a919738c783eec..a5f0c01477898dd6b2248a078026687c7b4338ad 100644 (file)
@@ -810,6 +810,7 @@ fn stmt_to_block(
                 id: resolver.next_node_id(),
                 span: rustc_span::DUMMY_SP,
                 tokens: None,
+                could_be_bare_literal: false,
             }
         }
 
index 21fad5f9af683fb20f1c4ae70b4d4288966a941b..5ac42c50c7240d22edb1adbd1b775248ac89d3fc 100644 (file)
@@ -74,39 +74,45 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
                 _ => return,
             };
 
-            // As this is a method call expression, we have at least one
-            // argument.
+            // As this is a method call expression, we have at least one argument.
             let receiver_arg = &args[0];
+            let receiver_ty = cx.typeck_results().expr_ty(receiver_arg);
+            let adjustments = cx.typeck_results().expr_adjustments(receiver_arg);
 
-            // Peel all `Box<_>` layers. We have to special case `Box` here as
-            // `Box` is the only thing that values can be moved out of via
-            // method call. `Box::new([1]).into_iter()` should trigger this
-            // lint.
-            let mut recv_ty = cx.typeck_results().expr_ty(receiver_arg);
-            let mut num_box_derefs = 0;
-            while recv_ty.is_box() {
-                num_box_derefs += 1;
-                recv_ty = recv_ty.boxed_ty();
-            }
+            let target = match adjustments.last() {
+                Some(Adjustment { kind: Adjust::Borrow(_), target }) => target,
+                _ => return,
+            };
 
-            // Make sure we found an array after peeling the boxes.
-            if !matches!(recv_ty.kind(), ty::Array(..)) {
-                return;
+            let types =
+                std::iter::once(receiver_ty).chain(adjustments.iter().map(|adj| adj.target));
+
+            let mut found_array = false;
+
+            for ty in types {
+                match ty.kind() {
+                    // If we run into a &[T; N] or &[T] first, there's nothing to warn about.
+                    // It'll resolve to the reference version.
+                    ty::Ref(_, inner_ty, _) if inner_ty.is_array() => return,
+                    ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => return,
+                    // Found an actual array type without matching a &[T; N] first.
+                    // This is the problematic case.
+                    ty::Array(..) => {
+                        found_array = true;
+                        break;
+                    }
+                    _ => {}
+                }
             }
 
-            // Make sure that there is an autoref coercion at the expected
-            // position. The first `num_box_derefs` adjustments are the derefs
-            // of the box.
-            match cx.typeck_results().expr_adjustments(receiver_arg).get(num_box_derefs) {
-                Some(Adjustment { kind: Adjust::Borrow(_), .. }) => {}
-                _ => return,
+            if !found_array {
+                return;
             }
 
             // Emit lint diagnostic.
-            let target = match *cx.typeck_results().expr_ty_adjusted(receiver_arg).kind() {
+            let target = match *target.kind() {
                 ty::Ref(_, inner_ty, _) if inner_ty.is_array() => "[T; N]",
                 ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Slice(..)) => "[T]",
-
                 // We know the original first argument type is an array type,
                 // we know that the first adjustment was an autoref coercion
                 // and we know that `IntoIterator` is the trait involved. The
@@ -135,7 +141,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
                         String::new(),
                         Applicability::MaybeIncorrect,
                     );
-                } else {
+                } else if receiver_ty.is_array() {
                     diag.multipart_suggestion(
                         "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value",
                         vec![
index afa2cfca1880fec96d8e200344748d938ab828e2..2850e7a6b44e95a485046701b98911e75a897ca3 100644 (file)
 use rustc_hir::{HirId, Node};
 use rustc_index::vec::Idx;
 use rustc_middle::lint::LintDiagnosticBuilder;
+use rustc_middle::ty::layout::{LayoutError, LayoutOf};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, Subst};
 use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, layout::LayoutError, Ty, TyCtxt};
-use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, Span};
-use rustc_target::abi::{LayoutOf, VariantIdx};
+use rustc_span::{BytePos, InnerSpan, MultiSpan, Span};
+use rustc_target::abi::VariantIdx;
 use rustc_trait_selection::traits::misc::can_type_implement_copy;
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
@@ -152,8 +153,8 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
 declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
 
 impl BoxPointers {
-    fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
-        for leaf in ty.walk() {
+    fn check_heap_type<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
+        for leaf in ty.walk(cx.tcx) {
             if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
                 if leaf_ty.is_box() {
                     cx.struct_span_lint(BOX_POINTERS, span, |lint| {
@@ -585,24 +586,6 @@ fn exit_lint_attrs(&mut self, _: &LateContext<'_>, _attrs: &[ast::Attribute]) {
 
     fn check_crate(&mut self, cx: &LateContext<'_>, krate: &hir::Crate<'_>) {
         self.check_missing_docs_attrs(cx, CRATE_DEF_ID, krate.module().inner, "the", "crate");
-
-        for macro_def in krate.exported_macros() {
-            // Non exported macros should be skipped, since `missing_docs` only
-            // applies to externally visible items.
-            if !cx.access_levels.is_exported(macro_def.def_id) {
-                continue;
-            }
-
-            let attrs = cx.tcx.hir().attrs(macro_def.hir_id());
-            let has_doc = attrs.iter().any(has_doc);
-            if !has_doc {
-                cx.struct_span_lint(
-                    MISSING_DOCS,
-                    cx.tcx.sess.source_map().guess_head_span(macro_def.span),
-                    |lint| lint.build("missing documentation for macro").emit(),
-                );
-            }
-        }
     }
 
     fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
@@ -636,6 +619,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
 
             hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Fn(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
@@ -1656,7 +1640,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                     ConstEquate(..) |
                     TypeWellFormedFromEnv(..) => continue,
                 };
-                if predicate.is_global() {
+                if predicate.is_global(cx.tcx) {
                     cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
                         lint.build(&format!(
                             "{} bound {} does not depend on any type \
@@ -2357,7 +2341,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     /// ### Example
     ///
     /// ```rust
-    /// #![feature(const_generics)]
+    /// #![feature(generic_const_exprs)]
     /// ```
     ///
     /// {{produces}}
@@ -3140,3 +3124,123 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
         }
     }
 }
+
+declare_lint! {
+    /// The `named_asm_labels` lint detects the use of named labels in the
+    /// inline `asm!` macro.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![feature(asm)]
+    /// fn main() {
+    ///     unsafe {
+    ///         asm!("foo: bar");
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// LLVM is allowed to duplicate inline assembly blocks for any
+    /// reason, for example when it is in a function that gets inlined. Because
+    /// of this, GNU assembler [local labels] *must* be used instead of labels
+    /// with a name. Using named labels might cause assembler or linker errors.
+    ///
+    /// See the [unstable book] for more details.
+    ///
+    /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
+    /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
+    pub NAMED_ASM_LABELS,
+    Deny,
+    "named labels in inline assembly",
+}
+
+declare_lint_pass!(NamedAsmLabels => [NAMED_ASM_LABELS]);
+
+impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
+        if let hir::Expr {
+            kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, .. }),
+            ..
+        } = expr
+        {
+            for (template_sym, template_snippet, template_span) in template_strs.iter() {
+                let template_str = &template_sym.as_str();
+                let find_label_span = |needle: &str| -> Option<Span> {
+                    if let Some(template_snippet) = template_snippet {
+                        let snippet = template_snippet.as_str();
+                        if let Some(pos) = snippet.find(needle) {
+                            let end = pos
+                                + &snippet[pos..]
+                                    .find(|c| c == ':')
+                                    .unwrap_or(snippet[pos..].len() - 1);
+                            let inner = InnerSpan::new(pos, end);
+                            return Some(template_span.from_inner(inner));
+                        }
+                    }
+
+                    None
+                };
+
+                let mut found_labels = Vec::new();
+
+                // A semicolon might not actually be specified as a separator for all targets, but it seems like LLVM accepts it always
+                let statements = template_str.split(|c| matches!(c, '\n' | ';'));
+                for statement in statements {
+                    // If there's a comment, trim it from the statement
+                    let statement = statement.find("//").map_or(statement, |idx| &statement[..idx]);
+                    let mut start_idx = 0;
+                    for (idx, _) in statement.match_indices(':') {
+                        let possible_label = statement[start_idx..idx].trim();
+                        let mut chars = possible_label.chars();
+                        if let Some(c) = chars.next() {
+                            // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $
+                            if (c.is_alphabetic() || matches!(c, '.' | '_'))
+                                && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$'))
+                            {
+                                found_labels.push(possible_label);
+                            } else {
+                                // If we encounter a non-label, there cannot be any further labels, so stop checking
+                                break;
+                            }
+                        } else {
+                            // Empty string means a leading ':' in this section, which is not a label
+                            break;
+                        }
+
+                        start_idx = idx + 1;
+                    }
+                }
+
+                debug!("NamedAsmLabels::check_expr(): found_labels: {:#?}", &found_labels);
+
+                if found_labels.len() > 0 {
+                    let spans = found_labels
+                        .into_iter()
+                        .filter_map(|label| find_label_span(label))
+                        .collect::<Vec<Span>>();
+                    // If there were labels but we couldn't find a span, combine the warnings and use the template span
+                    let target_spans: MultiSpan =
+                        if spans.len() > 0 { spans.into() } else { (*template_span).into() };
+
+                    cx.lookup_with_diagnostics(
+                            NAMED_ASM_LABELS,
+                            Some(target_spans),
+                            |diag| {
+                                let mut err =
+                                    diag.build("avoid using named labels in inline assembly");
+                                err.emit();
+                            },
+                            BuiltinLintDiagnostics::NamedAsmLabel(
+                                "only local labels of the form `<number>:` should be used in inline asm"
+                                    .to_string(),
+                            ),
+                        );
+                }
+            }
+        }
+    }
+}
index c2a46e997df4797660411333d3daf8b6317b211d..4c45e33db79c73976ddb1f07dc78eea6bde5d886 100644 (file)
@@ -31,7 +31,7 @@
 use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::middle::stability;
-use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
 use rustc_serialize::json::Json;
@@ -41,7 +41,7 @@
 use rustc_session::SessionLintStore;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
-use rustc_target::abi::LayoutOf;
+use rustc_target::abi;
 use tracing::debug;
 
 use std::cell::Cell;
@@ -1059,12 +1059,33 @@ fn path_generic_args(
     }
 }
 
-impl<'tcx> LayoutOf for LateContext<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
+    #[inline]
+    fn data_layout(&self) -> &abi::TargetDataLayout {
+        &self.tcx.data_layout
+    }
+}
+
+impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> {
+    #[inline]
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+}
+
+impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
+    #[inline]
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+}
+
+impl<'tcx> LayoutOfHelpers<'tcx> for LateContext<'tcx> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
index 052efa851f7cf5477a17fd8cb8c6f8afb28f0747..2070fd69d3f8eb7f59e75683e735b5ea2a774aba 100644 (file)
@@ -451,13 +451,8 @@ fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T)
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
         lint_callback!(cx, check_crate, krate);
-
-        hir_visit::walk_crate(cx, krate);
-        for attr in krate.non_exported_macro_attrs {
-            // This HIR ID is a lie, since the macro ID isn't available.
-            cx.visit_attribute(hir::CRATE_HIR_ID, attr);
-        }
-
+        tcx.hir().walk_toplevel_module(cx);
+        tcx.hir().walk_attributes(cx);
         lint_callback!(cx, check_crate_post, krate);
     })
 }
index e6cbfa0c9e29d2a55611ccebebf72c038c8e9a9b..66966e589e48a5e234d7f80e0d00fea78671e2c5 100644 (file)
@@ -37,10 +37,7 @@ fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
 
     let push = builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), &store, true);
     builder.levels.register_id(hir::CRATE_HIR_ID);
-    for macro_def in krate.exported_macros() {
-        builder.levels.register_id(macro_def.hir_id());
-    }
-    intravisit::walk_crate(&mut builder, krate);
+    tcx.hir().walk_toplevel_module(&mut builder);
     builder.levels.pop(push);
 
     builder.levels.build_map()
index c4008e77bab7cd0d633c7837f28b44f588e23585..ef4bda666ba062c7bb033084109649cda82bab23 100644 (file)
@@ -62,6 +62,8 @@
 mod types;
 mod unused;
 
+pub use array_into_iter::ARRAY_INTO_ITER;
+
 use rustc_ast as ast;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -168,6 +170,7 @@ macro_rules! late_lint_passes {
                 NonPanicFmt: NonPanicFmt,
                 NoopMethodCall: NoopMethodCall,
                 InvalidAtomicOrdering: InvalidAtomicOrdering,
+                NamedAsmLabels: NamedAsmLabels,
             ]
         );
     };
index 479cc00199f6adb33e54dc76fa47caf4cedb66f3..c14f16b6d11ba8ab194d039d284d0d760017f25a 100644 (file)
@@ -62,7 +62,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             _ => return,
         };
         let substs = cx.typeck_results().node_substs(expr.hir_id);
-        if substs.needs_subst() {
+        if substs.definitely_needs_subst(cx.tcx) {
             // We can't resolve on types that require monomorphization, so we don't handle them if
             // we need to perfom substitution.
             return;
index ef8aee8f64e29abb358026cdcc28dac94dd4ff0f..480f7756db3fe60476d766bc46ebffd852c38cf6 100644 (file)
@@ -6,14 +6,14 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
-use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable};
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol, DUMMY_SP};
 use rustc_target::abi::Abi;
-use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants};
+use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
 use if_chain::if_chain;
@@ -795,7 +795,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
         // Return the nullable type this Option-like enum can be safely represented with.
         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()) {
+            match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) {
                 (0, _) => unreachable!("Non-null optimisation extended to a non-zero value."),
                 (1, _) => {
                     return Some(get_nullable_type(cx, field_ty).unwrap());
@@ -1160,6 +1160,9 @@ struct ProhibitOpaqueTypes<'a, 'tcx> {
 
         impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
             type BreakTy = Ty<'tcx>;
+            fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                Some(self.cx.tcx)
+            }
 
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 match ty.kind() {
index be137884b4b27ee57be4087ce8fd858f97bfee5e..7a42e8c1037ba3dc58105a56a57d9368aa7b2a86 100644 (file)
@@ -1,7 +1,7 @@
 use crate::Lint;
 use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_ast as ast;
-use rustc_ast::util::parser;
+use rustc_ast::util::{classify, parser};
 use rustc_ast::{ExprKind, StmtKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{pluralize, Applicability};
@@ -382,6 +382,7 @@ enum UnusedDelimsCtx {
     FunctionArg,
     MethodArg,
     AssignedValue,
+    AssignedValueLetElse,
     IfCond,
     WhileCond,
     ForIterExpr,
@@ -398,7 +399,9 @@ fn from(ctx: UnusedDelimsCtx) -> &'static str {
         match ctx {
             UnusedDelimsCtx::FunctionArg => "function argument",
             UnusedDelimsCtx::MethodArg => "method argument",
-            UnusedDelimsCtx::AssignedValue => "assigned value",
+            UnusedDelimsCtx::AssignedValue | UnusedDelimsCtx::AssignedValueLetElse => {
+                "assigned value"
+            }
             UnusedDelimsCtx::IfCond => "`if` condition",
             UnusedDelimsCtx::WhileCond => "`while` condition",
             UnusedDelimsCtx::ForIterExpr => "`for` iterator expression",
@@ -441,18 +444,33 @@ fn check_unused_delims_expr(
         right_pos: Option<BytePos>,
     );
 
-    fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool {
+    fn is_expr_delims_necessary(
+        inner: &ast::Expr,
+        followed_by_block: bool,
+        followed_by_else: bool,
+    ) -> bool {
+        if followed_by_else {
+            match inner.kind {
+                ast::ExprKind::Binary(op, ..) if op.node.lazy() => return true,
+                _ if classify::expr_trailing_brace(inner).is_some() => return true,
+                _ => {}
+            }
+        }
+
         // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`
         let lhs_needs_parens = {
             let mut innermost = inner;
             loop {
-                if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind {
-                    innermost = lhs;
-                    if !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(innermost) {
-                        break true;
-                    }
-                } else {
-                    break false;
+                innermost = match &innermost.kind {
+                    ExprKind::Binary(_, lhs, _rhs) => lhs,
+                    ExprKind::Call(fn_, _params) => fn_,
+                    ExprKind::Cast(expr, _ty) => expr,
+                    ExprKind::Type(expr, _ty) => expr,
+                    ExprKind::Index(base, _subscript) => base,
+                    _ => break false,
+                };
+                if !classify::expr_requires_semi_to_be_stmt(innermost) {
+                    break true;
                 }
             }
         };
@@ -618,15 +636,12 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
     fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
         match s.kind {
             StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
-                if let Some(ref value) = local.init {
-                    self.check_unused_delims_expr(
-                        cx,
-                        &value,
-                        UnusedDelimsCtx::AssignedValue,
-                        false,
-                        None,
-                        None,
-                    );
+                if let Some((init, els)) = local.kind.init_else_opt() {
+                    let ctx = match els {
+                        None => UnusedDelimsCtx::AssignedValue,
+                        Some(_) => UnusedDelimsCtx::AssignedValueLetElse,
+                    };
+                    self.check_unused_delims_expr(cx, init, ctx, false, None, None);
                 }
             }
             StmtKind::Expr(ref expr) => {
@@ -702,7 +717,8 @@ fn check_unused_delims_expr(
     ) {
         match value.kind {
             ast::ExprKind::Paren(ref inner) => {
-                if !Self::is_expr_delims_necessary(inner, followed_by_block)
+                let followed_by_else = ctx == UnusedDelimsCtx::AssignedValueLetElse;
+                if !Self::is_expr_delims_necessary(inner, followed_by_block, followed_by_else)
                     && value.attrs.is_empty()
                     && !value.span.from_expansion()
                     && (ctx != UnusedDelimsCtx::LetScrutineeExpr
@@ -941,7 +957,7 @@ fn check_unused_delims_expr(
                 // FIXME(const_generics): handle paths when #67075 is fixed.
                 if let [stmt] = inner.stmts.as_slice() {
                     if let ast::StmtKind::Expr(ref expr) = stmt.kind {
-                        if !Self::is_expr_delims_necessary(expr, followed_by_block)
+                        if !Self::is_expr_delims_necessary(expr, followed_by_block, false)
                             && (ctx != UnusedDelimsCtx::AnonConst
                                 || matches!(expr.kind, ast::ExprKind::Lit(_)))
                             && !cx.sess().source_map().is_multiline(value.span)
index a1c507b4c847f93e00ab76b59529dd5b9278787d..8fb678e2d20fb0313633d4b9adccfdf41ab8e4f3 100644 (file)
     "incorrect use of inline assembly",
 }
 
-declare_lint! {
-    /// The `named_asm_labels` lint detects the use of named labels in the
-    /// inline `asm!` macro.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// fn main() {
-    ///     unsafe {
-    ///         asm!("foo: bar");
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// LLVM is allowed to duplicate inline assembly blocks for any
-    /// reason, for example when it is in a function that gets inlined. Because
-    /// of this, GNU assembler [local labels] *must* be used instead of labels
-    /// with a name. Using named labels might cause assembler or linker errors.
-    ///
-    /// See the [unstable book] for more details.
-    ///
-    /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
-    /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
-    pub NAMED_ASM_LABELS,
-    Deny,
-    "named labels in inline assembly",
-}
-
 declare_lint! {
     /// The `unsafe_op_in_unsafe_fn` lint detects unsafe operations in unsafe
     /// functions without an explicit unsafe block.
         INLINE_NO_SANITIZE,
         BAD_ASM_STYLE,
         ASM_SUB_REGISTER,
-        NAMED_ASM_LABELS,
         UNSAFE_OP_IN_UNSAFE_FN,
         INCOMPLETE_INCLUDE,
         CENUM_IMPL_DROP_CAST,
     Warn,
     "use of unsupported calling convention",
     @future_incompatible = FutureIncompatibleInfo {
-        reference: "issue #00000 <https://github.com/rust-lang/rust/issues/00000>",
+        reference: "issue #87678 <https://github.com/rust-lang/rust/issues/87678>",
     };
 }
 
index 4edfed034018759dc78c7b37e2ec4ca162ba9e84..4f07a0c67c13f43f50b1962a992b0c9b6ad50136 100644 (file)
@@ -270,34 +270,30 @@ extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
   Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
-  AttrBuilder B(Attr);
-  A->addAttributes(Index, B);
+  A->addAttribute(Index, Attr);
 }
 
 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
                                          unsigned Index,
                                          uint32_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  AttrBuilder B;
-  B.addAlignmentAttr(Bytes);
-  A->addAttributes(Index, B);
+  A->addAttribute(Index, Attribute::getWithAlignment(
+      A->getContext(), llvm::Align(Bytes)));
 }
 
 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
                                                uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  AttrBuilder B;
-  B.addDereferenceableAttr(Bytes);
-  A->addAttributes(Index, B);
+  A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(),
+                                                                Bytes));
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
                                                      unsigned Index,
                                                      uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  AttrBuilder B;
-  B.addDereferenceableOrNullAttr(Bytes);
-  A->addAttributes(Index, B);
+  A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes(
+      A->getContext(), Bytes));
 }
 
 extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
@@ -323,9 +319,8 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    const char *Name,
                                                    const char *Value) {
   Function *F = unwrap<Function>(Fn);
-  AttrBuilder B;
-  B.addAttribute(Name, Value);
-  F->addAttributes(Index, B);
+  F->addAttribute(Index, Attribute::get(
+      F->getContext(), StringRef(Name), StringRef(Value)));
 }
 
 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
index 394cb8389357f2f02633f06c2cf2f4f58b2a9748..99030febb7380210e25fbf2bedecada294f7d3bf 100644 (file)
@@ -450,6 +450,7 @@ fn load_proc_macro<'b>(
         &self,
         locator: &mut CrateLocator<'b>,
         path_kind: PathKind,
+        host_hash: Option<Svh>,
     ) -> Result<Option<(LoadResult, Option<Library>)>, CrateError>
     where
         'a: 'b,
@@ -459,7 +460,7 @@ fn load_proc_macro<'b>(
         let mut proc_macro_locator = locator.clone();
 
         // Try to load a proc macro
-        proc_macro_locator.is_proc_macro = Some(true);
+        proc_macro_locator.is_proc_macro = true;
 
         // Load the proc macro crate for the target
         let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
@@ -471,7 +472,7 @@ fn load_proc_macro<'b>(
                 Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)),
                 None => return Ok(None),
             };
-            locator.hash = locator.host_hash;
+            locator.hash = host_hash;
             // Use the locator when looking for the host proc macro crate, as that is required
             // so we want it to affect the error message
             (locator, result)
@@ -482,7 +483,7 @@ fn load_proc_macro<'b>(
         // Load the proc macro crate for the host
 
         locator.reset();
-        locator.is_proc_macro = Some(true);
+        locator.is_proc_macro = true;
         locator.target = &self.sess.host;
         locator.triple = TargetTriple::from_triple(config::host_triple());
         locator.filesearch = self.sess.host_filesearch(path_kind);
@@ -510,12 +511,9 @@ fn resolve_crate<'b>(
         name: Symbol,
         span: Span,
         dep_kind: CrateDepKind,
-        dep: Option<(&'b CratePaths, &'b CrateDep)>,
     ) -> CrateNum {
-        if dep.is_none() {
-            self.used_extern_options.insert(name);
-        }
-        self.maybe_resolve_crate(name, dep_kind, dep).unwrap_or_else(|err| {
+        self.used_extern_options.insert(name);
+        self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| {
             let missing_core =
                 self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
             err.report(&self.sess, span, missing_core)
@@ -551,21 +549,18 @@ fn maybe_resolve_crate<'b>(
                 &*self.metadata_loader,
                 name,
                 hash,
-                host_hash,
                 extra_filename,
                 false, // is_host
                 path_kind,
-                root,
-                Some(false), // is_proc_macro
             );
 
             match self.load(&mut locator)? {
                 Some(res) => (res, None),
                 None => {
                     dep_kind = CrateDepKind::MacrosOnly;
-                    match self.load_proc_macro(&mut locator, path_kind)? {
+                    match self.load_proc_macro(&mut locator, path_kind, host_hash)? {
                         Some(res) => res,
-                        None => return Err(locator.into_error()),
+                        None => return Err(locator.into_error(root.cloned())),
                     }
                 }
             }
@@ -605,7 +600,7 @@ fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, Cra
         // FIXME: why is this condition necessary? It was adding in #33625 but I
         // don't know why and the original author doesn't remember ...
         let can_reuse_cratenum =
-            locator.triple == self.sess.opts.target_triple || locator.is_proc_macro == Some(true);
+            locator.triple == self.sess.opts.target_triple || locator.is_proc_macro;
         Ok(Some(if can_reuse_cratenum {
             let mut result = LoadResult::Loaded(library);
             self.cstore.iter_crate_data(|cnum, data| {
@@ -755,7 +750,7 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         };
         info!("panic runtime not found -- loading {}", name);
 
-        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a panic runtime
@@ -795,7 +790,7 @@ fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
             );
         }
 
-        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+        let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit);
         let data = self.cstore.get_crate_data(cnum);
 
         // Sanity check the loaded crate to ensure it is indeed a profiler runtime
@@ -1015,7 +1010,7 @@ pub fn process_extern_crate(
                     CrateDepKind::Explicit
                 };
 
-                let cnum = self.resolve_crate(name, item.span, dep_kind, None);
+                let cnum = self.resolve_crate(name, item.span, dep_kind);
 
                 let path_len = definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
@@ -1034,7 +1029,7 @@ pub fn process_extern_crate(
     }
 
     pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum {
-        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, None);
+        let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit);
 
         self.update_extern_crate(
             cnum,
index 8d1bf6f55df09b0c54356babeb4c7cc4f1ea7b0a..d3512b6cf579e18e1d0cd4d70914ae7c7d1f1231 100644 (file)
 #[derive(Clone)]
 crate struct CrateLocator<'a> {
     // Immutable per-session configuration.
-    sess: &'a Session,
+    only_needs_metadata: bool,
+    sysroot: &'a Path,
     metadata_loader: &'a dyn MetadataLoader,
 
     // Immutable per-search configuration.
     crate_name: Symbol,
     exact_paths: Vec<CanonicalizedPath>,
     pub hash: Option<Svh>,
-    pub host_hash: Option<Svh>,
     extra_filename: Option<&'a str>,
     pub target: &'a Target,
     pub triple: TargetTriple,
     pub filesearch: FileSearch<'a>,
-    root: Option<&'a CratePaths>,
-    pub is_proc_macro: Option<bool>,
+    pub is_proc_macro: bool,
 
     // Mutable in-progress state or output.
-    rejected_via_hash: Vec<CrateMismatch>,
-    rejected_via_triple: Vec<CrateMismatch>,
-    rejected_via_kind: Vec<CrateMismatch>,
-    rejected_via_version: Vec<CrateMismatch>,
-    rejected_via_filename: Vec<CrateMismatch>,
+    crate_rejections: CrateRejections,
 }
 
 #[derive(Clone)]
@@ -298,15 +293,22 @@ impl<'a> CrateLocator<'a> {
         metadata_loader: &'a dyn MetadataLoader,
         crate_name: Symbol,
         hash: Option<Svh>,
-        host_hash: Option<Svh>,
         extra_filename: Option<&'a str>,
         is_host: bool,
         path_kind: PathKind,
-        root: Option<&'a CratePaths>,
-        is_proc_macro: Option<bool>,
     ) -> CrateLocator<'a> {
+        // The all loop is because `--crate-type=rlib --crate-type=rlib` is
+        // legal and produces both inside this type.
+        let is_rlib = sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
+        let needs_object_code = sess.opts.output_types.should_codegen();
+        // If we're producing an rlib, then we don't need object code.
+        // Or, if we're not producing object code, then we don't need it either
+        // (e.g., if we're a cdylib but emitting just metadata).
+        let only_needs_metadata = is_rlib || !needs_object_code;
+
         CrateLocator {
-            sess,
+            only_needs_metadata,
+            sysroot: &sess.sysroot,
             metadata_loader,
             crate_name,
             exact_paths: if hash.is_none() {
@@ -324,7 +326,6 @@ impl<'a> CrateLocator<'a> {
                 Vec::new()
             },
             hash,
-            host_hash,
             extra_filename,
             target: if is_host { &sess.host } else { &sess.target },
             triple: if is_host {
@@ -337,22 +338,17 @@ impl<'a> CrateLocator<'a> {
             } else {
                 sess.target_filesearch(path_kind)
             },
-            root,
-            is_proc_macro,
-            rejected_via_hash: Vec::new(),
-            rejected_via_triple: Vec::new(),
-            rejected_via_kind: Vec::new(),
-            rejected_via_version: Vec::new(),
-            rejected_via_filename: Vec::new(),
+            is_proc_macro: false,
+            crate_rejections: CrateRejections::default(),
         }
     }
 
     crate fn reset(&mut self) {
-        self.rejected_via_hash.clear();
-        self.rejected_via_triple.clear();
-        self.rejected_via_kind.clear();
-        self.rejected_via_version.clear();
-        self.rejected_via_filename.clear();
+        self.crate_rejections.via_hash.clear();
+        self.crate_rejections.via_triple.clear();
+        self.crate_rejections.via_kind.clear();
+        self.crate_rejections.via_version.clear();
+        self.crate_rejections.via_filename.clear();
     }
 
     crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> {
@@ -435,7 +431,7 @@ fn find_library_crate(
             };
             FileMatches
         });
-        self.rejected_via_kind.extend(staticlibs);
+        self.crate_rejections.via_kind.extend(staticlibs);
 
         // We have now collected all known libraries into a set of candidates
         // keyed of the filename hash listed. For each filename, we also have a
@@ -480,18 +476,11 @@ fn extract_lib(
     }
 
     fn needs_crate_flavor(&self, flavor: CrateFlavor) -> bool {
-        if flavor == CrateFlavor::Dylib && self.is_proc_macro == Some(true) {
+        if flavor == CrateFlavor::Dylib && self.is_proc_macro {
             return true;
         }
 
-        // The all loop is because `--crate-type=rlib --crate-type=rlib` is
-        // legal and produces both inside this type.
-        let is_rlib = self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib);
-        let needs_object_code = self.sess.opts.output_types.should_codegen();
-        // If we're producing an rlib, then we don't need object code.
-        // Or, if we're not producing object code, then we don't need it either
-        // (e.g., if we're a cdylib but emitting just metadata).
-        if is_rlib || !needs_object_code {
+        if self.only_needs_metadata {
             flavor == CrateFlavor::Rmeta
         } else {
             // we need all flavors (perhaps not true, but what we do for now)
@@ -591,7 +580,7 @@ fn extract_one(
             // candidates are all canonicalized, so we canonicalize the sysroot
             // as well.
             if let Some((prev, _)) = &ret {
-                let sysroot = &self.sess.sysroot;
+                let sysroot = self.sysroot;
                 let sysroot = sysroot.canonicalize().unwrap_or_else(|_| sysroot.to_path_buf());
                 if prev.starts_with(&sysroot) {
                     continue;
@@ -613,21 +602,20 @@ fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<S
         let found_version = metadata.get_rustc_version();
         if found_version != rustc_version {
             info!("Rejecting via version: expected {} got {}", rustc_version, found_version);
-            self.rejected_via_version
+            self.crate_rejections
+                .via_version
                 .push(CrateMismatch { path: libpath.to_path_buf(), got: found_version });
             return None;
         }
 
         let root = metadata.get_root();
-        if let Some(expected_is_proc_macro) = self.is_proc_macro {
-            let is_proc_macro = root.is_proc_macro_crate();
-            if is_proc_macro != expected_is_proc_macro {
-                info!(
-                    "Rejecting via proc macro: expected {} got {}",
-                    expected_is_proc_macro, is_proc_macro
-                );
-                return None;
-            }
+        if root.is_proc_macro_crate() != self.is_proc_macro {
+            info!(
+                "Rejecting via proc macro: expected {} got {}",
+                self.is_proc_macro,
+                root.is_proc_macro_crate(),
+            );
+            return None;
         }
 
         if self.exact_paths.is_empty() && self.crate_name != root.name() {
@@ -637,7 +625,7 @@ fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<S
 
         if root.triple() != &self.triple {
             info!("Rejecting via crate triple: expected {} got {}", self.triple, root.triple());
-            self.rejected_via_triple.push(CrateMismatch {
+            self.crate_rejections.via_triple.push(CrateMismatch {
                 path: libpath.to_path_buf(),
                 got: root.triple().to_string(),
             });
@@ -648,7 +636,8 @@ fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<S
         if let Some(expected_hash) = self.hash {
             if hash != expected_hash {
                 info!("Rejecting via hash: expected {} got {}", expected_hash, hash);
-                self.rejected_via_hash
+                self.crate_rejections
+                    .via_hash
                     .push(CrateMismatch { path: libpath.to_path_buf(), got: hash.to_string() });
                 return None;
             }
@@ -702,7 +691,8 @@ fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> {
                     dylibs.insert(loc_canon, PathKind::ExternFlag);
                 }
             } else {
-                self.rejected_via_filename
+                self.crate_rejections
+                    .via_filename
                     .push(CrateMismatch { path: loc.original().clone(), got: String::new() });
             }
         }
@@ -711,18 +701,14 @@ fn find_commandline_library(&mut self) -> Result<Option<Library>, CrateError> {
         Ok(self.extract_lib(rlibs, rmetas, dylibs)?.map(|(_, lib)| lib))
     }
 
-    crate fn into_error(self) -> CrateError {
+    crate fn into_error(self, root: Option<CratePaths>) -> CrateError {
         CrateError::LocatorCombined(CombinedLocatorError {
             crate_name: self.crate_name,
-            root: self.root.cloned(),
+            root,
             triple: self.triple,
             dll_prefix: self.target.dll_prefix.clone(),
             dll_suffix: self.target.dll_suffix.clone(),
-            rejected_via_hash: self.rejected_via_hash,
-            rejected_via_triple: self.rejected_via_triple,
-            rejected_via_kind: self.rejected_via_kind,
-            rejected_via_version: self.rejected_via_version,
-            rejected_via_filename: self.rejected_via_filename,
+            crate_rejections: self.crate_rejections,
         })
     }
 }
@@ -806,12 +792,9 @@ fn find_plugin_registrar_impl<'a>(
         metadata_loader,
         name,
         None, // hash
-        None, // host_hash
         None, // extra_filename
         true, // is_host
         PathKind::Crate,
-        None, // root
-        None, // is_proc_macro
     );
 
     match locator.maybe_load_library_crate()? {
@@ -819,7 +802,7 @@ fn find_plugin_registrar_impl<'a>(
             Some(dylib) => Ok(dylib.0),
             None => Err(CrateError::NonDylibPlugin(name)),
         },
-        None => Err(locator.into_error()),
+        None => Err(locator.into_error(None)),
     }
 }
 
@@ -852,6 +835,15 @@ struct CrateMismatch {
     got: String,
 }
 
+#[derive(Clone, Default)]
+struct CrateRejections {
+    via_hash: Vec<CrateMismatch>,
+    via_triple: Vec<CrateMismatch>,
+    via_kind: Vec<CrateMismatch>,
+    via_version: Vec<CrateMismatch>,
+    via_filename: Vec<CrateMismatch>,
+}
+
 /// Candidate rejection reasons collected during crate search.
 /// If no candidate is accepted, then these reasons are presented to the user,
 /// otherwise they are ignored.
@@ -861,11 +853,7 @@ struct CrateMismatch {
     triple: TargetTriple,
     dll_prefix: String,
     dll_suffix: String,
-    rejected_via_hash: Vec<CrateMismatch>,
-    rejected_via_triple: Vec<CrateMismatch>,
-    rejected_via_kind: Vec<CrateMismatch>,
-    rejected_via_version: Vec<CrateMismatch>,
-    rejected_via_filename: Vec<CrateMismatch>,
+    crate_rejections: CrateRejections,
 }
 
 crate enum CrateError {
@@ -974,7 +962,7 @@ impl CrateError {
                     Some(r) => format!(" which `{}` depends on", r.name),
                 };
                 let mut msg = "the following crate versions were found:".to_string();
-                let mut err = if !locator.rejected_via_hash.is_empty() {
+                let mut err = if !locator.crate_rejections.via_hash.is_empty() {
                     let mut err = struct_span_err!(
                         sess,
                         span,
@@ -984,7 +972,7 @@ impl CrateError {
                         add,
                     );
                     err.note("perhaps that crate needs to be recompiled?");
-                    let mismatches = locator.rejected_via_hash.iter();
+                    let mismatches = locator.crate_rejections.via_hash.iter();
                     for CrateMismatch { path, .. } in mismatches {
                         msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
                     }
@@ -995,7 +983,7 @@ impl CrateError {
                     }
                     err.note(&msg);
                     err
-                } else if !locator.rejected_via_triple.is_empty() {
+                } else if !locator.crate_rejections.via_triple.is_empty() {
                     let mut err = struct_span_err!(
                         sess,
                         span,
@@ -1005,7 +993,7 @@ impl CrateError {
                         locator.triple,
                         add,
                     );
-                    let mismatches = locator.rejected_via_triple.iter();
+                    let mismatches = locator.crate_rejections.via_triple.iter();
                     for CrateMismatch { path, got } in mismatches {
                         msg.push_str(&format!(
                             "\ncrate `{}`, target triple {}: {}",
@@ -1016,7 +1004,7 @@ impl CrateError {
                     }
                     err.note(&msg);
                     err
-                } else if !locator.rejected_via_kind.is_empty() {
+                } else if !locator.crate_rejections.via_kind.is_empty() {
                     let mut err = struct_span_err!(
                         sess,
                         span,
@@ -1026,13 +1014,13 @@ impl CrateError {
                         add,
                     );
                     err.help("please recompile that crate using --crate-type lib");
-                    let mismatches = locator.rejected_via_kind.iter();
+                    let mismatches = locator.crate_rejections.via_kind.iter();
                     for CrateMismatch { path, .. } in mismatches {
                         msg.push_str(&format!("\ncrate `{}`: {}", crate_name, path.display()));
                     }
                     err.note(&msg);
                     err
-                } else if !locator.rejected_via_version.is_empty() {
+                } else if !locator.crate_rejections.via_version.is_empty() {
                     let mut err = struct_span_err!(
                         sess,
                         span,
@@ -1045,7 +1033,7 @@ impl CrateError {
                         "please recompile that crate using this compiler ({})",
                         rustc_version(),
                     ));
-                    let mismatches = locator.rejected_via_version.iter();
+                    let mismatches = locator.crate_rejections.via_version.iter();
                     for CrateMismatch { path, got } in mismatches {
                         msg.push_str(&format!(
                             "\ncrate `{}` compiled by {}: {}",
@@ -1112,8 +1100,8 @@ impl CrateError {
                     err
                 };
 
-                if !locator.rejected_via_filename.is_empty() {
-                    let mismatches = locator.rejected_via_filename.iter();
+                if !locator.crate_rejections.via_filename.is_empty() {
+                    let mismatches = locator.crate_rejections.via_filename.iter();
                     for CrateMismatch { path, .. } in mismatches {
                         err.note(&format!(
                             "extern location for {} is of an unknown type: {}",
index 4e591b28f608781d8f4d13a61a3097034eab5643..dd44e0cb1fa90872c1f64cad00ddb3d52bd75eb3 100644 (file)
@@ -1100,7 +1100,13 @@ fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
                     let vis = self.get_visibility(child_index);
                     let def_id = self.local_def_id(child_index);
                     let res = Res::Def(kind, def_id);
-                    callback(Export { res, ident, vis, span });
+
+                    // FIXME: Macros are currently encoded twice, once as items and once as
+                    // reexports. We ignore the items here and only use the reexports.
+                    if !matches!(kind, DefKind::Macro(..)) {
+                        callback(Export { res, ident, vis, span });
+                    }
+
                     // For non-re-export structs and variants add their constructors to children.
                     // Re-export lists automatically contain constructors when necessary.
                     match kind {
index d9bbb03129975de9884dbf73d9ce61c174c8b60a..d8b9a4799760ef3d9cf79db8932c527a512de6ae 100644 (file)
@@ -448,16 +448,13 @@ fn encode_info_for_items(&mut self) {
         }
 
         krate.visit_all_item_likes(&mut self.as_deep_visitor());
-        for macro_def in krate.exported_macros() {
-            self.visit_macro_def(macro_def);
-        }
     }
 
     fn encode_def_path_table(&mut self) {
         let table = self.tcx.resolutions(()).definitions.def_path_table();
         if self.is_proc_macro {
             for def_index in std::iter::once(CRATE_DEF_INDEX)
-                .chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))
+                .chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
             {
                 let def_key = self.lazy(table.def_key(def_index));
                 let def_path_hash = self.lazy(table.def_path_hash(def_index));
@@ -509,11 +506,20 @@ fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
                                 let working_dir = &self.tcx.sess.opts.working_dir;
                                 match working_dir {
                                     RealFileName::LocalPath(absolute) => {
-                                        // If working_dir has not been remapped, then we emit a
-                                        // LocalPath variant as it's likely to be a valid path
-                                        RealFileName::LocalPath(
-                                            Path::new(absolute).join(path_to_file),
-                                        )
+                                        // Although neither working_dir or the file name were subject
+                                        // to path remapping, the concatenation between the two may
+                                        // be. Hence we need to do a remapping here.
+                                        let joined = Path::new(absolute).join(path_to_file);
+                                        let (joined, remapped) =
+                                            source_map.path_mapping().map_prefix(joined);
+                                        if remapped {
+                                            RealFileName::Remapped {
+                                                local_path: None,
+                                                virtual_name: joined,
+                                            }
+                                        } else {
+                                            RealFileName::LocalPath(joined)
+                                        }
                                     }
                                     RealFileName::Remapped { local_path: _, virtual_name } => {
                                         // If working_dir has been remapped, then we emit
@@ -1376,6 +1382,9 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
 
                 EntryKind::Fn(self.lazy(data))
             }
+            hir::ItemKind::Macro(ref macro_def) => {
+                EntryKind::MacroDef(self.lazy(macro_def.clone()))
+            }
             hir::ItemKind::Mod(ref m) => {
                 return self.encode_info_for_mod(item.def_id, m);
             }
@@ -1530,13 +1539,6 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
         }
     }
 
-    /// Serialize the text of exported macros
-    fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) {
-        let def_id = macro_def.def_id.to_def_id();
-        record!(self.tables.kind[def_id] <- EntryKind::MacroDef(self.lazy(macro_def.ast.clone())));
-        self.encode_ident_span(def_id, macro_def.ident);
-    }
-
     fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) {
         record!(self.tables.kind[def_id] <- kind);
         if encode_type {
@@ -1628,7 +1630,8 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
 
             let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
             let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied();
-            let macros = self.lazy(hir.krate().proc_macros.iter().map(|p| p.owner.local_def_index));
+            let macros =
+                self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
             let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
             for (i, span) in spans.into_iter().enumerate() {
                 let span = self.lazy(span);
@@ -1647,13 +1650,14 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
             // Normally, this information is encoded when we walk the items
             // defined in this crate. However, we skip doing that for proc-macro crates,
             // so we manually encode just the information that we need
-            for proc_macro in &hir.krate().proc_macros {
-                let id = proc_macro.owner.local_def_index;
-                let mut name = hir.name(*proc_macro);
-                let span = hir.span(*proc_macro);
+            for &proc_macro in &tcx.resolutions(()).proc_macros {
+                let id = proc_macro;
+                let proc_macro = hir.local_def_id_to_hir_id(proc_macro);
+                let mut name = hir.name(proc_macro);
+                let span = hir.span(proc_macro);
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
-                let attrs = hir.attrs(*proc_macro);
+                let attrs = hir.attrs(proc_macro);
                 let macro_kind = if tcx.sess.contains_name(attrs, sym::proc_macro) {
                     MacroKind::Bang
                 } else if tcx.sess.contains_name(attrs, sym::proc_macro_attribute) {
@@ -1671,10 +1675,10 @@ fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
                     bug!("Unknown proc-macro type for item {:?}", id);
                 };
 
-                let mut def_key = self.tcx.hir().def_key(proc_macro.owner);
+                let mut def_key = self.tcx.hir().def_key(id);
                 def_key.disambiguated_data.data = DefPathData::MacroNs(name);
 
-                let def_id = DefId::local(id);
+                let def_id = id.to_def_id();
                 record!(self.tables.def_kind[def_id] <- DefKind::Macro(macro_kind));
                 record!(self.tables.kind[def_id] <- EntryKind::ProcMacro(macro_kind));
                 record!(self.tables.attributes[def_id] <- attrs);
@@ -1906,9 +1910,6 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
         intravisit::walk_generics(self, generics);
         self.encode_info_for_generics(generics);
     }
-    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
-        self.encode_info_for_macro_def(macro_def);
-    }
 }
 
 impl EncodeContext<'a, 'tcx> {
@@ -1963,6 +1964,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
             hir::ItemKind::Static(..)
             | hir::ItemKind::Const(..)
             | hir::ItemKind::Fn(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
index a89d00e26ac192c4a175aec0f0e3dd7881747187..59db2c6636ff9e8495c612ab69c737a7b962b446 100644 (file)
@@ -9,8 +9,8 @@
 /// listed. These impls will appear in the implement_ty_decoder! macro.
 #[macro_export]
 macro_rules! arena_types {
-    ($macro:path, $args:tt, $tcx:lifetime) => (
-        $macro!($args, [
+    ($macro:path, $tcx:lifetime) => (
+        $macro!([
             [] layouts: rustc_target::abi::Layout,
             // AdtDef are interned and compared by address
             [] adt_def: rustc_middle::ty::AdtDef,
@@ -109,4 +109,4 @@ macro_rules! arena_types {
     )
 }
 
-arena_types!(rustc_arena::declare_arena, [], 'tcx);
+arena_types!(rustc_arena::declare_arena, 'tcx);
index 5c166c74004a3a7ff15ac57a0d254f8b8d055b4e..1351b4950f143cb9714bd4cc95fbe2ca7ba208ee 100644 (file)
@@ -394,20 +394,6 @@ fn visit_vis(&mut self, visibility: &'hir Visibility<'hir>) {
         }
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
-        // Exported macros are visited directly from the crate root,
-        // so they do not have `parent_node` set.
-        // Find the correct enclosing module from their DefKey.
-        let def_key = self.definitions.def_key(macro_def.def_id);
-        let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
-            self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
-        });
-        self.insert_owner(macro_def.def_id, OwnerNode::MacroDef(macro_def));
-        self.with_parent(parent, |this| {
-            this.insert_nested(macro_def.def_id);
-        });
-    }
-
     fn visit_variant(&mut self, v: &'hir Variant<'hir>, g: &'hir Generics<'hir>, item_id: HirId) {
         self.insert(v.span, v.id, Node::Variant(v));
         self.with_parent(v.id, |this| {
index c313146b072225913328a692daab2ac6d706bd55..e0b6039fe348f4bd0e24ed5581000ee9dec978b9 100644 (file)
@@ -7,10 +7,9 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::svh::Svh;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
-use rustc_hir::intravisit;
-use rustc_hir::intravisit::Visitor;
+use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::*;
 use rustc_index::vec::Idx;
@@ -218,6 +217,7 @@ pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
                 ItemKind::Static(..) => DefKind::Static,
                 ItemKind::Const(..) => DefKind::Const,
                 ItemKind::Fn(..) => DefKind::Fn,
+                ItemKind::Macro(..) => DefKind::Macro(MacroKind::Bang),
                 ItemKind::Mod(..) => DefKind::Mod,
                 ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
                 ItemKind::TyAlias(..) => DefKind::TyAlias,
@@ -266,7 +266,6 @@ pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
                 ExprKind::Closure(.., Some(_)) => DefKind::Generator,
                 _ => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
             },
-            Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
             Node::GenericParam(param) => match param.kind {
                 GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
                 GenericParamKind::Type { .. } => DefKind::TyParam,
@@ -520,6 +519,22 @@ pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
         }
     }
 
+    /// Walks the contents of a crate. See also `Crate::visit_all_items`.
+    pub fn walk_toplevel_module(self, visitor: &mut impl Visitor<'hir>) {
+        let (top_mod, span, hir_id) = self.get_module(CRATE_DEF_ID);
+        visitor.visit_mod(top_mod, span, hir_id);
+    }
+
+    /// Walks the attributes in a crate.
+    pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) {
+        let krate = self.krate();
+        for (&id, attrs) in krate.attrs.iter() {
+            for a in *attrs {
+                visitor.visit_attribute(id, a)
+            }
+        }
+    }
+
     pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
     where
         V: ItemLikeVisitor<'hir>,
@@ -543,15 +558,6 @@ pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
         }
     }
 
-    pub fn visit_exported_macros_in_krate<V>(&self, visitor: &mut V)
-    where
-        V: Visitor<'hir>,
-    {
-        for macro_def in self.krate().exported_macros() {
-            visitor.visit_macro_def(macro_def);
-        }
-    }
-
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
     /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
     pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
@@ -645,8 +651,6 @@ pub fn get_return_block(&self, id: HirId) -> Option<HirId> {
     /// in a module, trait, or impl.
     pub fn get_parent_item(&self, hir_id: HirId) -> HirId {
         if let Some((hir_id, _node)) = self.parent_owner_iter(hir_id).next() {
-            // A MacroDef does not have children.
-            debug_assert!(!matches!(_node, OwnerNode::MacroDef(_)));
             hir_id
         } else {
             CRATE_HIR_ID
@@ -774,13 +778,6 @@ pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> {
         }
     }
 
-    pub fn expect_macro_def(&self, id: HirId) -> &'hir MacroDef<'hir> {
-        match self.tcx.hir_owner(id.expect_owner()) {
-            Some(Owner { node: OwnerNode::MacroDef(macro_def) }) => macro_def,
-            _ => bug!("expected macro def, found {}", self.node_to_string(id)),
-        }
-    }
-
     pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> {
         match self.find(id) {
             Some(Node::Expr(expr)) => expr,
@@ -800,7 +797,6 @@ pub fn opt_name(&self, id: HirId) -> Option<Symbol> {
             Node::GenericParam(param) => param.name.ident().name,
             Node::Binding(&Pat { kind: PatKind::Binding(_, _, l, _), .. }) => l.name,
             Node::Ctor(..) => self.name(self.get_parent_item(id)),
-            Node::MacroDef(md) => md.ident.name,
             _ => return None,
         })
     }
@@ -867,7 +863,6 @@ pub fn opt_span(&self, hir_id: HirId) -> Option<Span> {
             Node::Infer(i) => i.span,
             Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
             Node::Local(local) => local.span,
-            Node::MacroDef(macro_def) => macro_def.span,
             Node::Crate(item) => item.inner,
         };
         Some(span)
@@ -955,7 +950,8 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx IndexedHir<'tc
         &tcx.untracked_resolutions.definitions,
         hcx,
     );
-    intravisit::walk_crate(&mut collector, tcx.untracked_crate);
+    let top_mod = tcx.untracked_crate.module();
+    collector.visit_mod(top_mod, top_mod.inner, CRATE_HIR_ID);
 
     let map = collector.finalize_and_compute_crate_hash();
     tcx.arena.alloc(map)
@@ -1013,7 +1009,6 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
-    tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
 
     let crate_hash: Fingerprint = stable_hasher.finish();
     Svh::new(crate_hash.to_smaller_hash())
@@ -1062,6 +1057,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
                 ItemKind::Static(..) => "static",
                 ItemKind::Const(..) => "const",
                 ItemKind::Fn(..) => "fn",
+                ItemKind::Macro(..) => "macro",
                 ItemKind::Mod(..) => "mod",
                 ItemKind::ForeignMod { .. } => "foreign mod",
                 ItemKind::GlobalAsm(..) => "global asm",
@@ -1118,7 +1114,6 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
         Some(Node::Lifetime(_)) => node_str("lifetime"),
         Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str),
         Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str),
-        Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str),
         Some(Node::Crate(..)) => String::from("root_crate"),
         None => format!("unknown node{}", id_str),
     }
index 158499bc0aef787661ac8e3164344293597f62c4..34aee4f1b3b3fc24703738a8be4c59927c4532c0 100644 (file)
@@ -170,7 +170,7 @@ pub fn provide(providers: &mut Providers) {
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
-    providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
+    providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
     providers.expn_that_defined = |tcx, id| {
         let id = id.expect_local();
         tcx.resolutions(()).definitions.expansion_that_defined(id)
index 0e72e916cc6acec3988d2dab011ebad5381c6d0c..6868be50f1d068d458a3f7568d9992881501345e 100644 (file)
@@ -31,6 +31,8 @@
 #![feature(box_patterns)]
 #![feature(core_intrinsics)]
 #![feature(discriminant_kind)]
+#![feature(exhaustive_patterns)]
+#![feature(if_let_guard)]
 #![feature(never_type)]
 #![feature(extern_types)]
 #![feature(new_uninit)]
@@ -52,6 +54,7 @@
 #![feature(try_reserve)]
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "512"]
 
 #[macro_use]
index 6ad68877235dc7d6453c65be964d44e5b278f05a..60cb78d902ee60f9dd49c6dab680907be6f2c758 100644 (file)
@@ -192,6 +192,7 @@ impl<'a> LintDiagnosticBuilder<'a> {
     /// Return the inner DiagnosticBuilder, first setting the primary message to `msg`.
     pub fn build(mut self, msg: &str) -> DiagnosticBuilder<'a> {
         self.0.set_primary_message(msg);
+        self.0.set_is_lint();
         self.0
     }
 
index 6c92c65a6dd975e7097293186414805d9fca92fa..bd4e83a42ef515c371bdd9ed0aa702b4d228a537 100644 (file)
@@ -94,6 +94,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
             ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id),
             ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id),
             ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id),
+            ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.id),
             ScopeData::Remainder(fsi) => write!(
                 fmt,
                 "Remainder {{ block: {:?}, first_statement_index: {}}}",
@@ -120,6 +121,10 @@ pub enum ScopeData {
     /// Scope of destructors for temporaries of node-id.
     Destruction,
 
+    /// Scope of the condition and then block of an if expression
+    /// Used for variables introduced in an if-let expression.
+    IfThen,
+
     /// Scope following a `let id = expr;` binding in a block.
     Remainder(FirstStatementIndex),
 }
index 5964efa78e9e928b8484a5a3fdece056cadc99d3..b6358f9929448cc22b1baa98ec7123d2da0f6617 100644 (file)
@@ -1,7 +1,7 @@
 //! The virtual memory representation of the MIR interpreter.
 
 use std::borrow::Cow;
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
 use std::iter;
 use std::ops::{Deref, Range};
 use std::ptr;
@@ -495,129 +495,6 @@ fn check_relocation_edges(&self, cx: &impl HasDataLayout, range: AllocRange) ->
     }
 }
 
-/// Uninitialized bytes.
-impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
-    /// Checks whether the given range  is entirely initialized.
-    ///
-    /// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte
-    /// indexes of the first contiguous uninitialized access.
-    fn is_init(&self, range: AllocRange) -> Result<(), Range<Size>> {
-        self.init_mask.is_range_initialized(range.start, range.end()) // `Size` addition
-    }
-
-    /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes`
-    /// error which will report the first range of bytes which is uninitialized.
-    fn check_init(&self, range: AllocRange) -> AllocResult {
-        self.is_init(range).or_else(|idx_range| {
-            Err(AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
-                access_offset: range.start,
-                access_size: range.size,
-                uninit_offset: idx_range.start,
-                uninit_size: idx_range.end - idx_range.start, // `Size` subtraction
-            })))
-        })
-    }
-
-    pub fn mark_init(&mut self, range: AllocRange, is_init: bool) {
-        if range.size.bytes() == 0 {
-            return;
-        }
-        assert!(self.mutability == Mutability::Mut);
-        self.init_mask.set_range(range.start, range.end(), is_init);
-    }
-}
-
-/// Run-length encoding of the uninit mask.
-/// Used to copy parts of a mask multiple times to another allocation.
-pub struct InitMaskCompressed {
-    /// Whether the first range is initialized.
-    initial: bool,
-    /// The lengths of ranges that are run-length encoded.
-    /// The initialization state of the ranges alternate starting with `initial`.
-    ranges: smallvec::SmallVec<[u64; 1]>,
-}
-
-impl InitMaskCompressed {
-    pub fn no_bytes_init(&self) -> bool {
-        // The `ranges` are run-length encoded and of alternating initialization state.
-        // So if `ranges.len() > 1` then the second block is an initialized range.
-        !self.initial && self.ranges.len() == 1
-    }
-}
-
-/// Transferring the initialization mask to other allocations.
-impl<Tag, Extra> Allocation<Tag, Extra> {
-    /// Creates a run-length encoding of the initialization mask.
-    pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed {
-        // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
-        // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
-        // the source and write it to the destination. Even if we optimized the memory accesses,
-        // we'd be doing all of this `repeat` times.
-        // Therefore we precompute a compressed version of the initialization mask of the source value and
-        // then write it back `repeat` times without computing any more information from the source.
-
-        // A precomputed cache for ranges of initialized / uninitialized bits
-        // 0000010010001110 will become
-        // `[5, 1, 2, 1, 3, 3, 1]`,
-        // where each element toggles the state.
-
-        let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
-        let initial = self.init_mask.get(range.start);
-        let mut cur_len = 1;
-        let mut cur = initial;
-
-        for i in 1..range.size.bytes() {
-            // FIXME: optimize to bitshift the current uninitialized block's bits and read the top bit.
-            if self.init_mask.get(range.start + Size::from_bytes(i)) == cur {
-                cur_len += 1;
-            } else {
-                ranges.push(cur_len);
-                cur_len = 1;
-                cur = !cur;
-            }
-        }
-
-        ranges.push(cur_len);
-
-        InitMaskCompressed { ranges, initial }
-    }
-
-    /// Applies multiple instances of the run-length encoding to the initialization mask.
-    pub fn mark_compressed_init_range(
-        &mut self,
-        defined: &InitMaskCompressed,
-        range: AllocRange,
-        repeat: u64,
-    ) {
-        // An optimization where we can just overwrite an entire range of initialization
-        // bits if they are going to be uniformly `1` or `0`.
-        if defined.ranges.len() <= 1 {
-            self.init_mask.set_range_inbounds(
-                range.start,
-                range.start + range.size * repeat, // `Size` operations
-                defined.initial,
-            );
-            return;
-        }
-
-        for mut j in 0..repeat {
-            j *= range.size.bytes();
-            j += range.start.bytes();
-            let mut cur = defined.initial;
-            for range in &defined.ranges {
-                let old_j = j;
-                j += range;
-                self.init_mask.set_range_inbounds(
-                    Size::from_bytes(old_j),
-                    Size::from_bytes(j),
-                    cur,
-                );
-                cur = !cur;
-            }
-        }
-    }
-}
-
 /// "Relocations" stores the provenance information of pointers stored in memory.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 pub struct Relocations<Tag = AllocId>(SortedMap<Size, Tag>);
@@ -704,35 +581,28 @@ pub struct InitMask {
 impl InitMask {
     pub const BLOCK_SIZE: u64 = 64;
 
-    pub fn new(size: Size, state: bool) -> Self {
-        let mut m = InitMask { blocks: vec![], len: Size::ZERO };
-        m.grow(size, state);
-        m
+    #[inline]
+    fn bit_index(bits: Size) -> (usize, usize) {
+        // BLOCK_SIZE is the number of bits that can fit in a `Block`.
+        // Each bit in a `Block` represents the initialization state of one byte of an allocation,
+        // so we use `.bytes()` here.
+        let bits = bits.bytes();
+        let a = bits / InitMask::BLOCK_SIZE;
+        let b = bits % InitMask::BLOCK_SIZE;
+        (usize::try_from(a).unwrap(), usize::try_from(b).unwrap())
     }
 
-    /// Checks whether the range `start..end` (end-exclusive) is entirely initialized.
-    ///
-    /// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
-    /// indexes for the first contiguous span of the uninitialized access.
     #[inline]
-    pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<Size>> {
-        if end > self.len {
-            return Err(self.len..end);
-        }
-
-        // FIXME(oli-obk): optimize this for allocations larger than a block.
-        let idx = (start.bytes()..end.bytes()).map(Size::from_bytes).find(|&i| !self.get(i));
+    fn size_from_bit_index(block: impl TryInto<u64>, bit: impl TryInto<u64>) -> Size {
+        let block = block.try_into().ok().unwrap();
+        let bit = bit.try_into().ok().unwrap();
+        Size::from_bytes(block * InitMask::BLOCK_SIZE + bit)
+    }
 
-        match idx {
-            Some(idx) => {
-                let uninit_end = (idx.bytes()..end.bytes())
-                    .map(Size::from_bytes)
-                    .find(|&i| self.get(i))
-                    .unwrap_or(end);
-                Err(idx..uninit_end)
-            }
-            None => Ok(()),
-        }
+    pub fn new(size: Size, state: bool) -> Self {
+        let mut m = InitMask { blocks: vec![], len: Size::ZERO };
+        m.grow(size, state);
+        m
     }
 
     pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
@@ -744,8 +614,8 @@ pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
     }
 
     pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
-        let (blocka, bita) = bit_index(start);
-        let (blockb, bitb) = bit_index(end);
+        let (blocka, bita) = Self::bit_index(start);
+        let (blockb, bitb) = Self::bit_index(end);
         if blocka == blockb {
             // First set all bits except the first `bita`,
             // then unset the last `64 - bitb` bits.
@@ -789,13 +659,13 @@ pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
 
     #[inline]
     pub fn get(&self, i: Size) -> bool {
-        let (block, bit) = bit_index(i);
+        let (block, bit) = Self::bit_index(i);
         (self.blocks[block] & (1 << bit)) != 0
     }
 
     #[inline]
     pub fn set(&mut self, i: Size, new_state: bool) {
-        let (block, bit) = bit_index(i);
+        let (block, bit) = Self::bit_index(i);
         self.set_bit(block, bit, new_state);
     }
 
@@ -825,12 +695,418 @@ pub fn grow(&mut self, amount: Size, new_state: bool) {
         self.len += amount;
         self.set_range_inbounds(start, start + amount, new_state); // `Size` operation
     }
+
+    /// Returns the index of the first bit in `start..end` (end-exclusive) that is equal to is_init.
+    fn find_bit(&self, start: Size, end: Size, is_init: bool) -> Option<Size> {
+        /// A fast implementation of `find_bit`,
+        /// which skips over an entire block at a time if it's all 0s (resp. 1s),
+        /// and finds the first 1 (resp. 0) bit inside a block using `trailing_zeros` instead of a loop.
+        ///
+        /// Note that all examples below are written with 8 (instead of 64) bit blocks for simplicity,
+        /// and with the least significant bit (and lowest block) first:
+        ///
+        ///          00000000|00000000
+        ///          ^      ^ ^      ^
+        ///   index: 0      7 8      15
+        ///
+        /// Also, if not stated, assume that `is_init = true`, that is, we are searching for the first 1 bit.
+        fn find_bit_fast(
+            init_mask: &InitMask,
+            start: Size,
+            end: Size,
+            is_init: bool,
+        ) -> Option<Size> {
+            /// Search one block, returning the index of the first bit equal to `is_init`.
+            fn search_block(
+                bits: Block,
+                block: usize,
+                start_bit: usize,
+                is_init: bool,
+            ) -> Option<Size> {
+                // For the following examples, assume this function was called with:
+                //   bits = 0b00111011
+                //   start_bit = 3
+                //   is_init = false
+                // Note that, for the examples in this function, the most significant bit is written first,
+                // which is backwards compared to the comments in `find_bit`/`find_bit_fast`.
+
+                // Invert bits so we're always looking for the first set bit.
+                //        ! 0b00111011
+                //   bits = 0b11000100
+                let bits = if is_init { bits } else { !bits };
+                // Mask off unused start bits.
+                //          0b11000100
+                //        & 0b11111000
+                //   bits = 0b11000000
+                let bits = bits & (!0 << start_bit);
+                // Find set bit, if any.
+                //   bit = trailing_zeros(0b11000000)
+                //   bit = 6
+                if bits == 0 {
+                    None
+                } else {
+                    let bit = bits.trailing_zeros();
+                    Some(InitMask::size_from_bit_index(block, bit))
+                }
+            }
+
+            if start >= end {
+                return None;
+            }
+
+            // Convert `start` and `end` to block indexes and bit indexes within each block.
+            // We must convert `end` to an inclusive bound to handle block boundaries correctly.
+            //
+            // For example:
+            //
+            //   (a) 00000000|00000000    (b) 00000000|
+            //       ^~~~~~~~~~~^             ^~~~~~~~~^
+            //     start       end          start     end
+            //
+            // In both cases, the block index of `end` is 1.
+            // But we do want to search block 1 in (a), and we don't in (b).
+            //
+            // We subtract 1 from both end positions to make them inclusive:
+            //
+            //   (a) 00000000|00000000    (b) 00000000|
+            //       ^~~~~~~~~~^              ^~~~~~~^
+            //     start    end_inclusive   start end_inclusive
+            //
+            // For (a), the block index of `end_inclusive` is 1, and for (b), it's 0.
+            // This provides the desired behavior of searching blocks 0 and 1 for (a),
+            // and searching only block 0 for (b).
+            // There is no concern of overflows since we checked for `start >= end` above.
+            let (start_block, start_bit) = InitMask::bit_index(start);
+            let end_inclusive = Size::from_bytes(end.bytes() - 1);
+            let (end_block_inclusive, _) = InitMask::bit_index(end_inclusive);
+
+            // Handle first block: need to skip `start_bit` bits.
+            //
+            // We need to handle the first block separately,
+            // because there may be bits earlier in the block that should be ignored,
+            // such as the bit marked (1) in this example:
+            //
+            //       (1)
+            //       -|------
+            //   (c) 01000000|00000000|00000001
+            //          ^~~~~~~~~~~~~~~~~~^
+            //        start              end
+            if let Some(i) =
+                search_block(init_mask.blocks[start_block], start_block, start_bit, is_init)
+            {
+                // If the range is less than a block, we may find a matching bit after `end`.
+                //
+                // For example, we shouldn't successfully find bit (2), because it's after `end`:
+                //
+                //             (2)
+                //       -------|
+                //   (d) 00000001|00000000|00000001
+                //        ^~~~~^
+                //      start end
+                //
+                // An alternative would be to mask off end bits in the same way as we do for start bits,
+                // but performing this check afterwards is faster and simpler to implement.
+                if i < end {
+                    return Some(i);
+                } else {
+                    return None;
+                }
+            }
+
+            // Handle remaining blocks.
+            //
+            // We can skip over an entire block at once if it's all 0s (resp. 1s).
+            // The block marked (3) in this example is the first block that will be handled by this loop,
+            // and it will be skipped for that reason:
+            //
+            //                   (3)
+            //                --------
+            //   (e) 01000000|00000000|00000001
+            //          ^~~~~~~~~~~~~~~~~~^
+            //        start              end
+            if start_block < end_block_inclusive {
+                // This loop is written in a specific way for performance.
+                // Notably: `..end_block_inclusive + 1` is used for an inclusive range instead of `..=end_block_inclusive`,
+                // and `.zip(start_block + 1..)` is used to track the index instead of `.enumerate().skip().take()`,
+                // because both alternatives result in significantly worse codegen.
+                // `end_block_inclusive + 1` is guaranteed not to wrap, because `end_block_inclusive <= end / BLOCK_SIZE`,
+                // and `BLOCK_SIZE` (the number of bits per block) will always be at least 8 (1 byte).
+                for (&bits, block) in init_mask.blocks[start_block + 1..end_block_inclusive + 1]
+                    .iter()
+                    .zip(start_block + 1..)
+                {
+                    if let Some(i) = search_block(bits, block, 0, is_init) {
+                        // If this is the last block, we may find a matching bit after `end`.
+                        //
+                        // For example, we shouldn't successfully find bit (4), because it's after `end`:
+                        //
+                        //                               (4)
+                        //                         -------|
+                        //   (f) 00000001|00000000|00000001
+                        //          ^~~~~~~~~~~~~~~~~~^
+                        //        start              end
+                        //
+                        // As above with example (d), we could handle the end block separately and mask off end bits,
+                        // but unconditionally searching an entire block at once and performing this check afterwards
+                        // is faster and much simpler to implement.
+                        if i < end {
+                            return Some(i);
+                        } else {
+                            return None;
+                        }
+                    }
+                }
+            }
+
+            None
+        }
+
+        #[cfg_attr(not(debug_assertions), allow(dead_code))]
+        fn find_bit_slow(
+            init_mask: &InitMask,
+            start: Size,
+            end: Size,
+            is_init: bool,
+        ) -> Option<Size> {
+            (start..end).find(|&i| init_mask.get(i) == is_init)
+        }
+
+        let result = find_bit_fast(self, start, end, is_init);
+
+        debug_assert_eq!(
+            result,
+            find_bit_slow(self, start, end, is_init),
+            "optimized implementation of find_bit is wrong for start={:?} end={:?} is_init={} init_mask={:#?}",
+            start,
+            end,
+            is_init,
+            self
+        );
+
+        result
+    }
+}
+
+/// A contiguous chunk of initialized or uninitialized memory.
+pub enum InitChunk {
+    Init(Range<Size>),
+    Uninit(Range<Size>),
 }
 
-#[inline]
-fn bit_index(bits: Size) -> (usize, usize) {
-    let bits = bits.bytes();
-    let a = bits / InitMask::BLOCK_SIZE;
-    let b = bits % InitMask::BLOCK_SIZE;
-    (usize::try_from(a).unwrap(), usize::try_from(b).unwrap())
+impl InitChunk {
+    #[inline]
+    pub fn is_init(&self) -> bool {
+        match self {
+            Self::Init(_) => true,
+            Self::Uninit(_) => false,
+        }
+    }
+
+    #[inline]
+    pub fn range(&self) -> Range<Size> {
+        match self {
+            Self::Init(r) => r.clone(),
+            Self::Uninit(r) => r.clone(),
+        }
+    }
+}
+
+impl InitMask {
+    /// Checks whether the range `start..end` (end-exclusive) is entirely initialized.
+    ///
+    /// Returns `Ok(())` if it's initialized. Otherwise returns a range of byte
+    /// indexes for the first contiguous span of the uninitialized access.
+    #[inline]
+    pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Range<Size>> {
+        if end > self.len {
+            return Err(self.len..end);
+        }
+
+        let uninit_start = self.find_bit(start, end, false);
+
+        match uninit_start {
+            Some(uninit_start) => {
+                let uninit_end = self.find_bit(uninit_start, end, true).unwrap_or(end);
+                Err(uninit_start..uninit_end)
+            }
+            None => Ok(()),
+        }
+    }
+
+    /// Returns an iterator, yielding a range of byte indexes for each contiguous region
+    /// of initialized or uninitialized bytes inside the range `start..end` (end-exclusive).
+    ///
+    /// The iterator guarantees the following:
+    /// - Chunks are nonempty.
+    /// - Chunks are adjacent (each range's start is equal to the previous range's end).
+    /// - Chunks span exactly `start..end` (the first starts at `start`, the last ends at `end`).
+    /// - Chunks alternate between [`InitChunk::Init`] and [`InitChunk::Uninit`].
+    #[inline]
+    pub fn range_as_init_chunks(&self, start: Size, end: Size) -> InitChunkIter<'_> {
+        assert!(end <= self.len);
+
+        let is_init = if start < end {
+            self.get(start)
+        } else {
+            // `start..end` is empty: there are no chunks, so use some arbitrary value
+            false
+        };
+
+        InitChunkIter { init_mask: self, is_init, start, end }
+    }
+}
+
+/// Yields [`InitChunk`]s. See [`InitMask::range_as_init_chunks`].
+pub struct InitChunkIter<'a> {
+    init_mask: &'a InitMask,
+    /// Whether the next chunk we will return is initialized.
+    /// If there are no more chunks, contains some arbitrary value.
+    is_init: bool,
+    /// The current byte index into `init_mask`.
+    start: Size,
+    /// The end byte index into `init_mask`.
+    end: Size,
+}
+
+impl<'a> Iterator for InitChunkIter<'a> {
+    type Item = InitChunk;
+
+    #[inline]
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.start >= self.end {
+            return None;
+        }
+
+        let end_of_chunk =
+            self.init_mask.find_bit(self.start, self.end, !self.is_init).unwrap_or(self.end);
+        let range = self.start..end_of_chunk;
+
+        let ret =
+            Some(if self.is_init { InitChunk::Init(range) } else { InitChunk::Uninit(range) });
+
+        self.is_init = !self.is_init;
+        self.start = end_of_chunk;
+
+        ret
+    }
+}
+
+/// Uninitialized bytes.
+impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
+    /// Checks whether the given range  is entirely initialized.
+    ///
+    /// Returns `Ok(())` if it's initialized. Otherwise returns the range of byte
+    /// indexes of the first contiguous uninitialized access.
+    fn is_init(&self, range: AllocRange) -> Result<(), Range<Size>> {
+        self.init_mask.is_range_initialized(range.start, range.end()) // `Size` addition
+    }
+
+    /// Checks that a range of bytes is initialized. If not, returns the `InvalidUninitBytes`
+    /// error which will report the first range of bytes which is uninitialized.
+    fn check_init(&self, range: AllocRange) -> AllocResult {
+        self.is_init(range).or_else(|idx_range| {
+            Err(AllocError::InvalidUninitBytes(Some(UninitBytesAccess {
+                access_offset: range.start,
+                access_size: range.size,
+                uninit_offset: idx_range.start,
+                uninit_size: idx_range.end - idx_range.start, // `Size` subtraction
+            })))
+        })
+    }
+
+    pub fn mark_init(&mut self, range: AllocRange, is_init: bool) {
+        if range.size.bytes() == 0 {
+            return;
+        }
+        assert!(self.mutability == Mutability::Mut);
+        self.init_mask.set_range(range.start, range.end(), is_init);
+    }
+}
+
+/// Run-length encoding of the uninit mask.
+/// Used to copy parts of a mask multiple times to another allocation.
+pub struct InitMaskCompressed {
+    /// Whether the first range is initialized.
+    initial: bool,
+    /// The lengths of ranges that are run-length encoded.
+    /// The initialization state of the ranges alternate starting with `initial`.
+    ranges: smallvec::SmallVec<[u64; 1]>,
+}
+
+impl InitMaskCompressed {
+    pub fn no_bytes_init(&self) -> bool {
+        // The `ranges` are run-length encoded and of alternating initialization state.
+        // So if `ranges.len() > 1` then the second block is an initialized range.
+        !self.initial && self.ranges.len() == 1
+    }
+}
+
+/// Transferring the initialization mask to other allocations.
+impl<Tag, Extra> Allocation<Tag, Extra> {
+    /// Creates a run-length encoding of the initialization mask; panics if range is empty.
+    ///
+    /// This is essentially a more space-efficient version of
+    /// `InitMask::range_as_init_chunks(...).collect::<Vec<_>>()`.
+    pub fn compress_uninit_range(&self, range: AllocRange) -> InitMaskCompressed {
+        // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
+        // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
+        // the source and write it to the destination. Even if we optimized the memory accesses,
+        // we'd be doing all of this `repeat` times.
+        // Therefore we precompute a compressed version of the initialization mask of the source value and
+        // then write it back `repeat` times without computing any more information from the source.
+
+        // A precomputed cache for ranges of initialized / uninitialized bits
+        // 0000010010001110 will become
+        // `[5, 1, 2, 1, 3, 3, 1]`,
+        // where each element toggles the state.
+
+        let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
+
+        let mut chunks = self.init_mask.range_as_init_chunks(range.start, range.end()).peekable();
+
+        let initial = chunks.peek().expect("range should be nonempty").is_init();
+
+        // Here we rely on `range_as_init_chunks` to yield alternating init/uninit chunks.
+        for chunk in chunks {
+            let len = chunk.range().end.bytes() - chunk.range().start.bytes();
+            ranges.push(len);
+        }
+
+        InitMaskCompressed { ranges, initial }
+    }
+
+    /// Applies multiple instances of the run-length encoding to the initialization mask.
+    pub fn mark_compressed_init_range(
+        &mut self,
+        defined: &InitMaskCompressed,
+        range: AllocRange,
+        repeat: u64,
+    ) {
+        // An optimization where we can just overwrite an entire range of initialization
+        // bits if they are going to be uniformly `1` or `0`.
+        if defined.ranges.len() <= 1 {
+            self.init_mask.set_range_inbounds(
+                range.start,
+                range.start + range.size * repeat, // `Size` operations
+                defined.initial,
+            );
+            return;
+        }
+
+        for mut j in 0..repeat {
+            j *= range.size.bytes();
+            j += range.start.bytes();
+            let mut cur = defined.initial;
+            for range in &defined.ranges {
+                let old_j = j;
+                j += range;
+                self.init_mask.set_range_inbounds(
+                    Size::from_bytes(old_j),
+                    Size::from_bytes(j),
+                    cur,
+                );
+                cur = !cur;
+            }
+        }
+    }
 }
index dd9ac7f5c3955321c5ed8e9d7cf727a47dbd39a2..4628c24292f02a168454b25f54a5ce3ccce306ea 100644 (file)
@@ -125,7 +125,9 @@ macro_rules! throw_machine_stop {
 
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMaybeUninit};
 
-pub use self::allocation::{alloc_range, AllocRange, Allocation, InitMask, Relocations};
+pub use self::allocation::{
+    alloc_range, AllocRange, Allocation, InitChunk, InitChunkIter, InitMask, Relocations,
+};
 
 pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
 
index fa7c0670e8ce6a5c90c2ff9156cf3b4c513195a1..c63613ae3af29b097ea4a562f0c9bd5505869746 100644 (file)
@@ -38,7 +38,7 @@ pub fn const_eval_resolve(
         ct: ty::Unevaluated<'tcx>,
         span: Option<Span>,
     ) -> EvalToConstValueResult<'tcx> {
-        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) {
             Ok(Some(instance)) => {
                 let cid = GlobalId { instance, promoted: ct.promoted };
                 self.const_eval_global_id(param_env, cid, span)
index b66995afc6db66c5c57dd54f14eb2ade020a1146..83f6e79d5fcf674dfbc8f3bb36bee4f3827bf78e 100644 (file)
@@ -242,6 +242,7 @@ pub struct Body<'tcx> {
 
 impl<'tcx> Body<'tcx> {
     pub fn new(
+        tcx: TyCtxt<'tcx>,
         source: MirSource<'tcx>,
         basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
         source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
@@ -284,7 +285,7 @@ pub fn new(
             predecessor_cache: PredecessorCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
         };
-        body.is_polymorphic = body.has_param_types_or_consts();
+        body.is_polymorphic = body.definitely_has_param_types_or_consts(tcx);
         body
     }
 
@@ -294,7 +295,7 @@ pub fn new(
     /// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
     /// crate.
     pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
-        let mut body = Body {
+        Body {
             phase: MirPhase::Build,
             source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
             basic_blocks,
@@ -310,9 +311,7 @@ pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) ->
             is_polymorphic: false,
             predecessor_cache: PredecessorCache::new(),
             is_cyclic: GraphIsCyclicCache::new(),
-        };
-        body.is_polymorphic = body.has_param_types_or_consts();
-        body
+        }
     }
 
     #[inline]
@@ -412,8 +411,7 @@ pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a
     /// Returns an iterator over all function arguments.
     #[inline]
     pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
-        let arg_count = self.arg_count;
-        (1..arg_count + 1).map(Local::new)
+        (1..self.arg_count + 1).map(Local::new)
     }
 
     /// Returns an iterator over all user-defined variables and compiler-generated temporaries (all
@@ -422,9 +420,12 @@ pub fn args_iter(&self) -> impl Iterator<Item = Local> + ExactSizeIterator {
     pub fn vars_and_temps_iter(
         &self,
     ) -> impl DoubleEndedIterator<Item = Local> + ExactSizeIterator {
-        let arg_count = self.arg_count;
-        let local_count = self.local_decls.len();
-        (arg_count + 1..local_count).map(Local::new)
+        (self.arg_count + 1..self.local_decls.len()).map(Local::new)
+    }
+
+    #[inline]
+    pub fn drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator<Item = LocalDecl<'tcx>> + 'a {
+        self.local_decls.drain(self.arg_count + 1..)
     }
 
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@@ -1664,13 +1665,10 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
             AscribeUserType(box (ref place, ref c_ty), ref variance) => {
                 write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
             }
-            Coverage(box ref coverage) => {
-                if let Some(rgn) = &coverage.code_region {
-                    write!(fmt, "Coverage::{:?} for {:?}", coverage.kind, rgn)
-                } else {
-                    write!(fmt, "Coverage::{:?}", coverage.kind)
-                }
+            Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => {
+                write!(fmt, "Coverage::{:?} for {:?}", kind, rgn)
             }
+            Coverage(box ref coverage) => write!(fmt, "Coverage::{:?}", coverage.kind),
             CopyNonOverlapping(box crate::mir::CopyNonOverlapping {
                 ref src,
                 ref dst,
index 45ea3e3d9f35e1cbe27776c895661e347c14822a..af7f7796522606a536f190e10ec748270c45b745 100644 (file)
@@ -587,14 +587,12 @@ fn super_terminator(&mut self,
                                 InlineAsmOperand::In { value, .. } => {
                                     self.visit_operand(value, location);
                                 }
-                                InlineAsmOperand::Out { place, .. } => {
-                                    if let Some(place) = place {
-                                        self.visit_place(
-                                            place,
-                                            PlaceContext::MutatingUse(MutatingUseContext::Store),
-                                            location,
-                                        );
-                                    }
+                                InlineAsmOperand::Out { place: Some(place), .. } => {
+                                    self.visit_place(
+                                        place,
+                                        PlaceContext::MutatingUse(MutatingUseContext::Store),
+                                        location,
+                                    );
                                 }
                                 InlineAsmOperand::InOut { in_value, out_place, .. } => {
                                     self.visit_operand(in_value, location);
@@ -610,7 +608,8 @@ fn super_terminator(&mut self,
                                 | InlineAsmOperand::SymFn { value } => {
                                     self.visit_constant(value, location);
                                 }
-                                InlineAsmOperand::SymStatic { def_id: _ } => {}
+                                InlineAsmOperand::Out { place: None, .. }
+                                | InlineAsmOperand::SymStatic { def_id: _ } => {}
                             }
                         }
                     }
index 68de7f29193d8f61797996c481e82fbdfce92c7e..c93996162e3e372b491ce58f55d3927a39fe67d2 100644 (file)
         desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param)  }
     }
 
+    query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
+        desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) }
+    }
+
     /// Records the type of every item.
     query type_of(key: DefId) -> Ty<'tcx> {
-        desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) }
+        desc { |tcx|
+            "{action} `{path}`",
+            action = {
+                use rustc_hir::def::DefKind;
+                match tcx.def_kind(key) {
+                    DefKind::TyAlias => "expanding type alias",
+                    DefKind::TraitAlias => "expanding trait alias",
+                    _ => "computing type of",
+                }
+            },
+            path = tcx.def_path_str(key),
+        }
         cache_on_disk_if { key.is_local() }
     }
 
     }
 
     query try_unify_abstract_consts(key: (
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
+        ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
     )) -> bool {
         desc {
             |tcx| "trying to unify the generic constants {} and {}",
-            tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
+            tcx.def_path_str(key.0.def.did), tcx.def_path_str(key.1.def.did)
         }
     }
 
         desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
     }
 
+    query own_existential_vtable_entries(
+        key: ty::PolyExistentialTraitRef<'tcx>
+    ) -> &'tcx [DefId] {
+        desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
+    }
+
     query vtable_entries(key: ty::PolyTraitRef<'tcx>)
                         -> &'tcx [ty::VtblEntry<'tcx>] {
         desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
         cache_on_disk_if { false }
     }
 
-    query layout_raw(
-        env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
-    ) -> Result<&'tcx rustc_target::abi::Layout, ty::layout::LayoutError<'tcx>> {
-        desc { "computing layout of `{}`", env.value }
+    /// Computes the layout of a type. Note that this implicitly
+    /// executes in "reveal all" mode, and will normalize the input type.
+    query layout_of(
+        key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
+    ) -> Result<ty::layout::TyAndLayout<'tcx>, ty::layout::LayoutError<'tcx>> {
+        desc { "computing layout of `{}`", key.value }
     }
 
     query dylib_dependency_formats(_: CrateNum)
index 48337b8cb9617eee988c3d2806097059a2c81dec..91a64e163e7c0172efd2cb58395ed574cd96402b 100644 (file)
@@ -14,7 +14,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::RangeEnd;
 use rustc_index::newtype_index;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
 use rustc_middle::infer::canonical::Canonical;
 use rustc_middle::middle::region;
 use rustc_middle::mir::{
@@ -223,6 +223,7 @@ pub enum ExprKind<'tcx> {
     },
     /// An `if` expression.
     If {
+        if_then_scope: region::Scope,
         cond: ExprId,
         then: ExprId,
         else_opt: Option<ExprId>,
@@ -716,17 +717,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     PatKind::Variant { adt_def, variant_index, .. } => {
                         Some(&adt_def.variants[variant_index])
                     }
-                    _ => {
-                        if let ty::Adt(adt, _) = self.ty.kind() {
-                            if !adt.is_enum() {
-                                Some(&adt.variants[VariantIdx::new(0)])
-                            } else {
-                                None
-                            }
-                        } else {
-                            None
-                        }
-                    }
+                    _ => self.ty.ty_adt_def().and_then(|adt| {
+                        if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
+                    }),
                 };
 
                 if let Some(variant) = variant {
index 457e80c1663ac413660e65d5db0ed0b7a720dd48..74edb17fe32f1af9e4daccc8c1ab447c412893e8 100644 (file)
@@ -17,7 +17,6 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::Constness;
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::SmallVec;
@@ -306,6 +305,9 @@ pub enum ObligationCauseCode<'tcx> {
     /// Intrinsic has wrong type
     IntrinsicType,
 
+    /// A let else block does not diverge
+    LetElse,
+
     /// Method receiver
     MethodReceiver,
 
@@ -497,7 +499,7 @@ pub enum ImplSource<'tcx, N> {
     /// for some type parameter. The `Vec<N>` represents the
     /// obligations incurred from normalizing the where-clause (if
     /// any).
-    Param(Vec<N>, Constness),
+    Param(Vec<N>, ty::BoundConstness),
 
     /// Virtual calls through an object.
     Object(ImplSourceObjectData<'tcx, N>),
index 36db258e92d200e41eacc6b5c55a9afda11f2643..4edb6a327b0352f60fd61f148e8e491ee8507600 100644 (file)
@@ -437,15 +437,15 @@ fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
 }
 
 macro_rules! impl_arena_allocatable_decoders {
-    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+    ([$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
         $(
             impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]);
         )*
     }
 }
 
-rustc_hir::arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
-arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
+rustc_hir::arena_types!(impl_arena_allocatable_decoders, 'tcx);
+arena_types!(impl_arena_allocatable_decoders, 'tcx);
 
 #[macro_export]
 macro_rules! implement_ty_decoder {
index c78151271c171fdb8d8f30da1ab80833ada2d52c..869b2ab9dbcbc5a02495d8b515f6963ad1f10e6c 100644 (file)
@@ -1,6 +1,5 @@
 use crate::mir::interpret::ConstValue;
 use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::subst::InternalSubsts;
 use crate::ty::{self, Ty, TyCtxt};
 use crate::ty::{ParamEnv, ParamEnvAnd};
 use rustc_errors::ErrorReported;
@@ -100,7 +99,7 @@ pub fn from_opt_const_arg_anon_const(
             }
             _ => ty::ConstKind::Unevaluated(ty::Unevaluated {
                 def: def.to_global(),
-                substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
+                substs_: None,
                 promoted: None,
             }),
         };
index f2db95d162b888363fc7d016fe40af5c7f261e45..7188eed5445516bd28a58d089b47a175df2f84ab 100644 (file)
@@ -1,4 +1,5 @@
 use std::convert::TryInto;
+use std::fmt;
 
 use crate::mir::interpret::{AllocId, ConstValue, Scalar};
 use crate::mir::Promoted;
 
 use super::ScalarInt;
 /// An unevaluated, potentially generic, constant.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
+///
+/// If `substs_` is `None` it means that this anon const
+/// still has its default substs.
+///
+/// We check for all possible substs in `fn default_anon_const_substs`,
+/// so refer to that check for more info.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
 #[derive(Hash, HashStable)]
-pub struct Unevaluated<'tcx> {
+pub struct Unevaluated<'tcx, P = Option<Promoted>> {
     pub def: ty::WithOptConstParam<DefId>,
-    pub substs: SubstsRef<'tcx>,
-    pub promoted: Option<Promoted>,
+    pub substs_: Option<SubstsRef<'tcx>>,
+    pub promoted: P,
+}
+
+impl<'tcx> Unevaluated<'tcx> {
+    #[inline]
+    pub fn shrink(self) -> Unevaluated<'tcx, ()> {
+        debug_assert_eq!(self.promoted, None);
+        Unevaluated { def: self.def, substs_: self.substs_, promoted: () }
+    }
+}
+
+impl<'tcx> Unevaluated<'tcx, ()> {
+    #[inline]
+    pub fn expand(self) -> Unevaluated<'tcx> {
+        Unevaluated { def: self.def, substs_: self.substs_, promoted: None }
+    }
+}
+
+impl<'tcx, P: Default> Unevaluated<'tcx, P> {
+    #[inline]
+    pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
+        Unevaluated { def, substs_: Some(substs), promoted: Default::default() }
+    }
+}
+
+impl<'tcx, P: Default + PartialEq + fmt::Debug> Unevaluated<'tcx, P> {
+    #[inline]
+    pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
+        self.substs_.unwrap_or_else(|| {
+            // We must not use the parents default substs for promoted constants
+            // as that can result in incorrect substs and calls the `default_anon_const_substs`
+            // for something that might not actually be a constant.
+            debug_assert_eq!(self.promoted, Default::default());
+            tcx.default_anon_const_substs(self.def.did)
+        })
+    }
 }
 
 /// Represents a constant in Rust.
@@ -109,7 +151,7 @@ pub(super) fn try_eval(
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
     ) -> Option<Result<ConstValue<'tcx>, ErrorReported>> {
-        if let ConstKind::Unevaluated(Unevaluated { def, substs, promoted }) = self {
+        if let ConstKind::Unevaluated(unevaluated) = self {
             use crate::mir::interpret::ErrorHandled;
 
             // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
@@ -118,29 +160,32 @@ pub(super) fn try_eval(
             // Note that we erase regions *before* calling `with_reveal_all_normalized`,
             // so that we don't try to invoke this query with
             // any region variables.
-            let param_env_and_substs = tcx
+            let param_env_and = tcx
                 .erase_regions(param_env)
                 .with_reveal_all_normalized(tcx)
-                .and(tcx.erase_regions(substs));
+                .and(tcx.erase_regions(unevaluated));
 
             // HACK(eddyb) when the query key would contain inference variables,
             // attempt using identity substs and `ParamEnv` instead, that will succeed
             // when the expression doesn't depend on any parameters.
             // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
             // we can call `infcx.const_eval_resolve` which handles inference variables.
-            let param_env_and_substs = if param_env_and_substs.needs_infer() {
-                tcx.param_env(def.did).and(InternalSubsts::identity_for_item(tcx, def.did))
+            let param_env_and = if param_env_and.needs_infer() {
+                tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
+                    def: unevaluated.def,
+                    substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)),
+                    promoted: unevaluated.promoted,
+                })
             } else {
-                param_env_and_substs
+                param_env_and
             };
 
             // FIXME(eddyb) maybe the `const_eval_*` methods should take
-            // `ty::ParamEnvAnd<SubstsRef>` instead of having them separate.
-            let (param_env, substs) = param_env_and_substs.into_parts();
+            // `ty::ParamEnvAnd` instead of having them separate.
+            let (param_env, unevaluated) = param_env_and.into_parts();
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            match tcx.const_eval_resolve(param_env, ty::Unevaluated { def, substs, promoted }, None)
-            {
+            match tcx.const_eval_resolve(param_env, unevaluated, None) {
                 // NOTE(eddyb) `val` contains no lifetimes/types/consts,
                 // and we use the original type, so nothing from `substs`
                 // (which may be identity substs, see above),
index 89542a1ebabe276ae0ae844d486865e6888a5097..de7c6d9e095303a9f0d4bd7463852f335eff390e 100644 (file)
@@ -1420,8 +1420,8 @@ pub fn borrowck_mode(self) -> BorrowckMode {
     #[inline]
     pub fn lazy_normalization(self) -> bool {
         let features = self.features();
-        // Note: We do not enable lazy normalization for `min_const_generics`.
-        features.const_generics || features.lazy_normalization_consts
+        // Note: We only use lazy normalization for generic const expressions.
+        features.generic_const_exprs
     }
 
     #[inline]
index 759d1a017aa2a0cf5e192cce45405ff8e502a862..63eb55ed1a6208121d0e479810ae80209b0bce03 100644 (file)
@@ -21,7 +21,9 @@ pub fn erase_regions<T>(self, value: T) -> T
         T: TypeFoldable<'tcx>,
     {
         // If there's nothing to erase avoid performing the query at all
-        if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
+        if !value
+            .has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS)
+        {
             return value;
         }
         debug!("erase_regions({:?})", value);
index 1aa6c84dbc414586ed0b28d8ee00e11b3545cd2b..796ca650bdd77f55bd1f7c6df12175c39a300904 100644 (file)
@@ -33,7 +33,7 @@ pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
 #[derive(Clone, Debug, TypeFoldable)]
 pub enum TypeError<'tcx> {
     Mismatch,
-    ConstnessMismatch(ExpectedFound<hir::Constness>),
+    ConstnessMismatch(ExpectedFound<ty::BoundConstness>),
     UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
     AbiMismatch(ExpectedFound<abi::Abi>),
     Mutability,
@@ -102,7 +102,7 @@ fn report_maybe_different(
             CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
             Mismatch => write!(f, "types differ"),
             ConstnessMismatch(values) => {
-                write!(f, "expected {} fn, found {} fn", values.expected, values.found)
+                write!(f, "expected {} bound, found {} bound", values.expected, values.found)
             }
             UnsafetyMismatch(values) => {
                 write!(f, "expected {} fn, found {} fn", values.expected, values.found)
@@ -279,13 +279,10 @@ pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             }
             ty::FnDef(..) => "fn item".into(),
             ty::FnPtr(_) => "fn pointer".into(),
-            ty::Dynamic(ref inner, ..) => {
-                if let Some(principal) = inner.principal() {
-                    format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
-                } else {
-                    "trait object".into()
-                }
+            ty::Dynamic(ref inner, ..) if let Some(principal) = inner.principal() => {
+                format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
             }
+            ty::Dynamic(..) => "trait object".into(),
             ty::Closure(..) => "closure".into(),
             ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
             ty::GeneratorWitness(..) => "generator witness".into(),
@@ -365,20 +362,19 @@ pub fn note_and_explain_type_err(
                         // Issue #63167
                         db.note("distinct uses of `impl Trait` result in different opaque types");
                     }
-                    (ty::Float(_), ty::Infer(ty::IntVar(_))) => {
+                    (ty::Float(_), ty::Infer(ty::IntVar(_)))
                         if let Ok(
                             // Issue #53280
                             snippet,
-                        ) = self.sess.source_map().span_to_snippet(sp)
-                        {
-                            if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
-                                db.span_suggestion(
-                                    sp,
-                                    "use a float literal",
-                                    format!("{}.0", snippet),
-                                    MachineApplicable,
-                                );
-                            }
+                        ) = self.sess.source_map().span_to_snippet(sp) =>
+                    {
+                        if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
+                            db.span_suggestion(
+                                sp,
+                                "use a float literal",
+                                format!("{}.0", snippet),
+                                MachineApplicable,
+                            );
                         }
                     }
                     (ty::Param(expected), ty::Param(found)) => {
index 04df706d908423256a82fef9f1d06343b2de35fa..a078b6fb742a7b179a0686190b46a23aef3f1e91 100644 (file)
@@ -34,6 +34,12 @@ pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
         result.flags
     }
 
+    pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
+        let mut result = FlagComputation::new();
+        result.add_unevaluated_const(uv);
+        result.flags
+    }
+
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | flags;
     }
@@ -91,7 +97,7 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) {
             &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
 
             &ty::Param(_) => {
-                self.add_flags(TypeFlags::HAS_TY_PARAM);
+                self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM);
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
 
@@ -246,8 +252,8 @@ fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) {
             ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => {
                 self.add_substs(substs);
             }
-            ty::PredicateKind::ConstEvaluatable(_def_id, substs) => {
-                self.add_substs(substs);
+            ty::PredicateKind::ConstEvaluatable(uv) => {
+                self.add_unevaluated_const(uv);
             }
             ty::PredicateKind::ConstEquate(expected, found) => {
                 self.add_const(expected);
@@ -292,7 +298,7 @@ fn add_const(&mut self, c: &ty::Const<'_>) {
                 self.add_bound_var(debruijn);
             }
             ty::ConstKind::Param(_) => {
-                self.add_flags(TypeFlags::HAS_CT_PARAM);
+                self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM);
                 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
             }
             ty::ConstKind::Placeholder(_) => {
@@ -304,8 +310,24 @@ fn add_const(&mut self, c: &ty::Const<'_>) {
         }
     }
 
-    fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
-        self.add_substs(ct.substs);
+    fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'tcx, P>) {
+        // The generic arguments of unevaluated consts are a bit special,
+        // see the `rustc-dev-guide` for more information.
+        //
+        // FIXME(@lcnr): Actually add a link here.
+        if let Some(substs) = ct.substs_ {
+            // If they are available, we treat them as ordinary generic arguments.
+            self.add_substs(substs);
+        } else {
+            // Otherwise, we add `HAS_UNKNOWN_DEFAULT_CONST_SUBSTS` to signify
+            // that our const may potentially refer to generic parameters.
+            //
+            // Note that depending on which generic parameters are actually
+            // used in this constant, we may not actually refer to any generic
+            // parameters at all.
+            self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
+            self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS);
+        }
         self.add_flags(TypeFlags::HAS_CT_PROJECTION);
     }
 
index a40210d5a3622c29f7033abfbae18cc676038252..a04b0a7ef61363b39226653c0a3a8df3981d36f6 100644 (file)
@@ -74,8 +74,14 @@ fn has_escaping_bound_vars(&self) -> bool {
         self.has_vars_bound_at_or_above(ty::INNERMOST)
     }
 
+    fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool {
+        self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value()
+            == Some(FoundFlags)
+    }
+
     fn has_type_flags(&self, flags: TypeFlags) -> bool {
-        self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
+        self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value()
+            == Some(FoundFlags)
     }
     fn has_projections(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_PROJECTION)
@@ -86,8 +92,18 @@ fn has_opaque_types(&self) -> bool {
     fn references_error(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_ERROR)
     }
-    fn has_param_types_or_consts(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
+    fn potentially_has_param_types_or_consts(&self) -> bool {
+        self.has_type_flags(
+            TypeFlags::HAS_KNOWN_TY_PARAM
+                | TypeFlags::HAS_KNOWN_CT_PARAM
+                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
+        )
+    }
+    fn definitely_has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(
+            tcx,
+            TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM,
+        )
     }
     fn has_infer_regions(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -108,13 +124,18 @@ fn has_placeholders(&self) -> bool {
                 | TypeFlags::HAS_CT_PLACEHOLDER,
         )
     }
-    fn needs_subst(&self) -> bool {
-        self.has_type_flags(TypeFlags::NEEDS_SUBST)
+    fn potentially_needs_subst(&self) -> bool {
+        self.has_type_flags(
+            TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
+        )
+    }
+    fn definitely_needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST)
     }
     /// "Free" regions in this context means that it has any region
     /// that is not (a) erased or (b) late-bound.
-    fn has_free_regions(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
+    fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
     }
 
     fn has_erased_regions(&self) -> bool {
@@ -122,15 +143,25 @@ fn has_erased_regions(&self) -> bool {
     }
 
     /// True if there are any un-erased free regions.
-    fn has_erasable_regions(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
+    fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
+        self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
+    }
+
+    /// Indicates whether this value definitely references only 'global'
+    /// generic parameters that are the same regardless of what fn we are
+    /// in. This is used for caching.
+    ///
+    /// Note that this function is pessimistic and may incorrectly return
+    /// `false`.
+    fn is_known_global(&self) -> bool {
+        !self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES)
     }
 
     /// Indicates whether this value references only 'global'
     /// generic parameters that are the same regardless of what fn we are
     /// in. This is used for caching.
-    fn is_global(&self) -> bool {
-        !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
+    fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool {
+        !self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES)
     }
 
     /// True if there are any late-bound regions
@@ -182,6 +213,10 @@ fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         c.super_fold_with(self)
     }
 
+    fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+        p.super_fold_with(self)
+    }
+
     fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
         bug!("most type folders should not be folding MIR datastructures: {:?}", c)
     }
@@ -189,6 +224,17 @@ fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'t
 
 pub trait TypeVisitor<'tcx>: Sized {
     type BreakTy = !;
+    /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
+    /// are not yet supplied.
+    ///
+    /// Returning `None` for this method is only recommended if the `TypeVisitor`
+    /// does not care about default anon const substs, as it ignores generic parameters,
+    /// and fetching the default substs would cause a query cycle.
+    ///
+    /// For visitors which return `None` we completely skip the default substs in `ty::Unevaluated::super_visit_with`.
+    /// This means that incorrectly returning `None` can very quickly lead to ICE or other critical bugs, so be careful and
+    /// try to return an actual `tcx` if possible.
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>>;
 
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
@@ -209,6 +255,10 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
         c.super_visit_with(self)
     }
 
+    fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+        uv.super_visit_with(self)
+    }
+
     fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
         p.super_visit_with(self)
     }
@@ -301,7 +351,8 @@ pub fn any_free_region_meets(
         value: &impl TypeFoldable<'tcx>,
         callback: impl FnMut(ty::Region<'tcx>) -> bool,
     ) -> bool {
-        struct RegionVisitor<F> {
+        struct RegionVisitor<'tcx, F> {
+            tcx: TyCtxt<'tcx>,
             /// The index of a binder *just outside* the things we have
             /// traversed. If we encounter a bound region bound by this
             /// binder or one outer to it, it appears free. Example:
@@ -323,12 +374,16 @@ struct RegionVisitor<F> {
             callback: F,
         }
 
-        impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
+        impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<'tcx, F>
         where
             F: FnMut(ty::Region<'tcx>) -> bool,
         {
             type BreakTy = ();
 
+            fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                Some(self.tcx)
+            }
+
             fn visit_binder<T: TypeFoldable<'tcx>>(
                 &mut self,
                 t: &Binder<'tcx, T>,
@@ -356,7 +411,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
 
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 // We're only interested in types involving regions
-                if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
+                if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
                     ty.super_visit_with(self)
                 } else {
                     ControlFlow::CONTINUE
@@ -364,7 +419,9 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             }
         }
 
-        value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break()
+        value
+            .visit_with(&mut RegionVisitor { tcx: self, outer_index: ty::INNERMOST, callback })
+            .is_break()
     }
 }
 
@@ -708,7 +765,7 @@ fn collect_late_bound_regions<T>(
     where
         T: TypeFoldable<'tcx>,
     {
-        let mut collector = LateBoundRegionsCollector::new(just_constraint);
+        let mut collector = LateBoundRegionsCollector::new(self, just_constraint);
         let result = value.as_ref().skip_binder().visit_with(&mut collector);
         assert!(result.is_continue()); // should never have stopped early
         collector.regions
@@ -775,6 +832,11 @@ pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
 impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
     type BreakTy = ();
 
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        // Anonymous constants do not contain bound vars in their substs by default.
+        None
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &Binder<'tcx, T>,
@@ -989,6 +1051,11 @@ struct HasEscapingVarsVisitor {
 impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
     type BreakTy = FoundEscapingVars;
 
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        // Anonymous constants do not contain bound vars in their substs by default.
+        None
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &Binder<'tcx, T>,
@@ -1053,25 +1120,28 @@ fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Sel
 struct FoundFlags;
 
 // FIXME: Optimize for checking for infer flags
-struct HasTypeFlagsVisitor {
+struct HasTypeFlagsVisitor<'tcx> {
+    tcx: Option<TyCtxt<'tcx>>,
     flags: ty::TypeFlags,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
+impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> {
     type BreakTy = FoundFlags;
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        bug!("we shouldn't call this method as we manually look at ct substs");
+    }
 
     #[inline]
-    fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
-        debug!(
-            "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
-            t,
-            t.flags(),
-            self.flags
-        );
-        if t.flags().intersects(self.flags) {
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let flags = t.flags();
+        debug!("HasTypeFlagsVisitor: t={:?} flags={:?} self.flags={:?}", t, flags, self.flags);
+        if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
-            ControlFlow::CONTINUE
+            match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+                true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, t),
+                _ => ControlFlow::CONTINUE,
+            }
         }
     }
 
@@ -1093,27 +1163,144 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
         if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
         } else {
-            ControlFlow::CONTINUE
+            match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+                true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, c),
+                _ => ControlFlow::CONTINUE,
+            }
+        }
+    }
+
+    #[inline]
+    fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let flags = FlagComputation::for_unevaluated_const(uv);
+        debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags);
+        if flags.intersects(self.flags) {
+            ControlFlow::Break(FoundFlags)
+        } else {
+            match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+                true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, uv),
+                _ => ControlFlow::CONTINUE,
+            }
         }
     }
 
     #[inline]
     fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
+        let flags = predicate.inner.flags;
         debug!(
-            "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
-            predicate, predicate.inner.flags, self.flags
+            "HasTypeFlagsVisitor: predicate={:?} flags={:?} self.flags={:?}",
+            predicate, flags, self.flags
         );
-        if predicate.inner.flags.intersects(self.flags) {
+        if flags.intersects(self.flags) {
             ControlFlow::Break(FoundFlags)
+        } else {
+            match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+                true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, predicate),
+                _ => ControlFlow::CONTINUE,
+            }
+        }
+    }
+}
+
+struct UnknownConstSubstsVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    flags: ty::TypeFlags,
+}
+
+impl<'tcx> UnknownConstSubstsVisitor<'tcx> {
+    /// This is fairly cold and we don't want to
+    /// bloat the size of the `HasTypeFlagsVisitor`.
+    #[inline(never)]
+    pub fn search<T: TypeFoldable<'tcx>>(
+        visitor: &HasTypeFlagsVisitor<'tcx>,
+        v: T,
+    ) -> ControlFlow<FoundFlags> {
+        if visitor.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) {
+            v.super_visit_with(&mut UnknownConstSubstsVisitor {
+                tcx: visitor.tcx.unwrap(),
+                flags: visitor.flags,
+            })
         } else {
             ControlFlow::CONTINUE
         }
     }
 }
 
+impl<'tcx> TypeVisitor<'tcx> for UnknownConstSubstsVisitor<'tcx> {
+    type BreakTy = FoundFlags;
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        bug!("we shouldn't call this method as we manually look at ct substs");
+    }
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+            t.super_visit_with(self)
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+
+    #[inline]
+    fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if uv.substs_.is_none() {
+            self.tcx
+                .default_anon_const_substs(uv.def.did)
+                .visit_with(&mut HasTypeFlagsVisitor { tcx: Some(self.tcx), flags: self.flags })
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+
+    #[inline]
+    fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+            predicate.super_visit_with(self)
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    /// This is a HACK(const_generics) and should probably not be needed.
+    /// Might however be perf relevant, so who knows.
+    ///
+    /// FIXME(@lcnr): explain this function a bit more
+    pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T {
+        v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self })
+    }
+}
+
+struct ExposeDefaultConstSubstsFolder<'tcx> {
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeFolder<'tcx> for ExposeDefaultConstSubstsFolder<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+            ty.super_fold_with(self)
+        } else {
+            ty
+        }
+    }
+
+    fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+        if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
+            pred.super_fold_with(self)
+        } else {
+            pred
+        }
+    }
+}
+
 /// Collects all the late-bound regions at the innermost binding level
 /// into a hash set.
-struct LateBoundRegionsCollector {
+struct LateBoundRegionsCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
     current_index: ty::DebruijnIndex,
     regions: FxHashSet<ty::BoundRegionKind>,
 
@@ -1127,9 +1314,10 @@ struct LateBoundRegionsCollector {
     just_constrained: bool,
 }
 
-impl LateBoundRegionsCollector {
-    fn new(just_constrained: bool) -> Self {
+impl LateBoundRegionsCollector<'tcx> {
+    fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self {
         LateBoundRegionsCollector {
+            tcx,
             current_index: ty::INNERMOST,
             regions: Default::default(),
             just_constrained,
@@ -1137,7 +1325,11 @@ fn new(just_constrained: bool) -> Self {
     }
 }
 
-impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
+impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &Binder<'tcx, T>,
index 80c99872dd7663e0fd405e581654ea5208e89bb2..f7ab9dd82ac738971450a43ea912ba456ea56a8e 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::DUMMY_SP;
+use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::call::{
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
 };
@@ -42,6 +42,7 @@ fn repr_discr<'tcx>(
 }
 
 impl IntegerExt for Integer {
+    #[inline]
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> {
         match (*self, signed) {
             (I8, false) => tcx.types.u8,
@@ -149,6 +150,7 @@ pub trait PrimitiveExt {
 }
 
 impl PrimitiveExt for Primitive {
+    #[inline]
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             Int(i, signed) => i.to_ty(tcx, signed),
@@ -160,6 +162,7 @@ fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 
     /// Return an *integer* type matching this primitive.
     /// Useful in particular when dealing with enum discriminants.
+    #[inline]
     fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
         match *self {
             Int(i, signed) => i.to_ty(tcx, signed),
@@ -205,10 +208,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-fn layout_raw<'tcx>(
+fn layout_of<'tcx>(
     tcx: TyCtxt<'tcx>,
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
     ty::tls::with_related_context(tcx, move |icx| {
         let (param_env, ty) = query.into_parts();
 
@@ -220,21 +223,33 @@ fn layout_raw<'tcx>(
         let icx = ty::tls::ImplicitCtxt { layout_depth: icx.layout_depth + 1, ..icx.clone() };
 
         ty::tls::enter_context(&icx, |_| {
+            let param_env = param_env.with_reveal_all_normalized(tcx);
+            let unnormalized_ty = ty;
+            let ty = tcx.normalize_erasing_regions(param_env, ty);
+            if ty != unnormalized_ty {
+                // Ensure this layout is also cached for the normalized type.
+                return tcx.layout_of(param_env.and(ty));
+            }
+
             let cx = LayoutCx { tcx, param_env };
-            let layout = cx.layout_raw_uncached(ty);
+
+            let layout = cx.layout_of_uncached(ty)?;
+            let layout = TyAndLayout { ty, layout };
+
+            cx.record_layout_for_printing(layout);
+
             // Type-level uninhabitedness should always imply ABI uninhabitedness.
-            if let Ok(layout) = layout {
-                if tcx.conservative_is_privately_uninhabited(param_env.and(ty)) {
-                    assert!(layout.abi.is_uninhabited());
-                }
+            if tcx.conservative_is_privately_uninhabited(param_env.and(ty)) {
+                assert!(layout.abi.is_uninhabited());
             }
-            layout
+
+            Ok(layout)
         })
     })
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { layout_raw, ..*providers };
+    *providers = ty::query::Providers { layout_of, ..*providers };
 }
 
 pub struct LayoutCx<'tcx, C> {
@@ -492,14 +507,14 @@ fn univariant_uninterned(
         })
     }
 
-    fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
+    fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'tcx>> {
         let tcx = self.tcx;
         let param_env = self.param_env;
         let dl = self.data_layout();
         let scalar_unit = |value: Primitive| {
             let bits = value.size(dl).bits();
             assert!(bits <= 128);
-            Scalar { value, valid_range: 0..=(!0 >> (128 - bits)) }
+            Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } }
         };
         let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
 
@@ -512,11 +527,14 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
             // Basic scalars.
             ty::Bool => tcx.intern_layout(Layout::scalar(
                 self,
-                Scalar { value: Int(I8, false), valid_range: 0..=1 },
+                Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } },
             )),
             ty::Char => tcx.intern_layout(Layout::scalar(
                 self,
-                Scalar { value: Int(I32, false), valid_range: 0..=0x10FFFF },
+                Scalar {
+                    value: Int(I32, false),
+                    valid_range: WrappingRange { start: 0, end: 0x10FFFF },
+                },
             )),
             ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
             ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
@@ -526,7 +544,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
             }),
             ty::FnPtr(_) => {
                 let mut ptr = scalar_unit(Pointer);
-                ptr.valid_range = 1..=*ptr.valid_range.end();
+                ptr.valid_range = ptr.valid_range.with_start(1);
                 tcx.intern_layout(Layout::scalar(self, ptr))
             }
 
@@ -544,7 +562,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
             ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
                 let mut data_ptr = scalar_unit(Pointer);
                 if !ty.is_unsafe_ptr() {
-                    data_ptr.valid_range = 1..=*data_ptr.valid_range.end();
+                    data_ptr.valid_range = data_ptr.valid_range.with_start(1);
                 }
 
                 let pointee = tcx.normalize_erasing_regions(param_env, pointee);
@@ -560,7 +578,7 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                     ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
                     ty::Dynamic(..) => {
                         let mut vtable = scalar_unit(Pointer);
-                        vtable.valid_range = 1..=*vtable.valid_range.end();
+                        vtable.valid_range = vtable.valid_range.with_start(1);
                         vtable
                     }
                     _ => return Err(LayoutError::Unknown(unsized_part)),
@@ -886,7 +904,9 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                 let present_first = match present_first {
                     Some(present_first) => present_first,
                     // Uninhabited because it has no variants, or only absent ones.
-                    None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)),
+                    None if def.is_enum() => {
+                        return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout);
+                    }
                     // If it's a struct, still compute a layout so that we can still compute the
                     // field offsets.
                     None => VariantIdx::new(0),
@@ -933,14 +953,14 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                             if let Bound::Included(start) = start {
                                 // FIXME(eddyb) this might be incorrect - it doesn't
                                 // account for wrap-around (end < start) ranges.
-                                assert!(*scalar.valid_range.start() <= start);
-                                scalar.valid_range = start..=*scalar.valid_range.end();
+                                assert!(scalar.valid_range.start <= start);
+                                scalar.valid_range.start = start;
                             }
                             if let Bound::Included(end) = end {
                                 // FIXME(eddyb) this might be incorrect - it doesn't
                                 // account for wrap-around (end < start) ranges.
-                                assert!(*scalar.valid_range.end() >= end);
-                                scalar.valid_range = *scalar.valid_range.start()..=end;
+                                assert!(scalar.valid_range.end >= end);
+                                scalar.valid_range.end = end;
                             }
 
                             // Update `largest_niche` if we have introduced a larger niche.
@@ -1256,7 +1276,10 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
                 let tag_mask = !0u128 >> (128 - ity.size().bits());
                 let tag = Scalar {
                     value: Int(ity, signed),
-                    valid_range: (min as u128 & tag_mask)..=(max as u128 & tag_mask),
+                    valid_range: WrappingRange {
+                        start: (min as u128 & tag_mask),
+                        end: (max as u128 & tag_mask),
+                    },
                 };
                 let mut abi = Abi::Aggregate { sized: true };
                 if tag.value.size(dl) == size {
@@ -1362,11 +1385,9 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<
 
             // Types with no meaningful known layout.
             ty::Projection(_) | ty::Opaque(..) => {
-                let normalized = tcx.normalize_erasing_regions(param_env, ty);
-                if ty == normalized {
-                    return Err(LayoutError::Unknown(ty));
-                }
-                tcx.layout_raw(param_env.and(normalized))?
+                // NOTE(eddyb) `layout_of` query should've normalized these away,
+                // if that was possible, so there's no reason to try again here.
+                return Err(LayoutError::Unknown(ty));
             }
 
             ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
@@ -1535,7 +1556,10 @@ fn generator_layout(
         let max_discr = (info.variant_fields.len() - 1) as u128;
         let discr_int = Integer::fit_unsigned(max_discr);
         let discr_int_ty = discr_int.to_ty(tcx, false);
-        let tag = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr };
+        let tag = Scalar {
+            value: Primitive::Int(discr_int, false),
+            valid_range: WrappingRange { start: 0, end: max_discr },
+        };
         let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
         let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
 
@@ -1703,7 +1727,7 @@ fn generator_layout(
         Ok(layout)
     }
 
-    /// This is invoked by the `layout_raw` query to record the final
+    /// This is invoked by the `layout_of` query to record the final
     /// layout of each type.
     #[inline(always)]
     fn record_layout_for_printing(&self, layout: TyAndLayout<'tcx>) {
@@ -1718,7 +1742,9 @@ fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) {
         // Ignore layouts that are done with non-empty environments or
         // non-monomorphic layouts, as the user only wants to see the stuff
         // resulting from the final codegen session.
-        if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
+        if layout.ty.definitely_has_param_types_or_consts(self.tcx)
+            || !self.param_env.caller_bounds().is_empty()
+        {
             return;
         }
 
@@ -1762,22 +1788,18 @@ fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) {
             let field_info: Vec<_> = flds
                 .iter()
                 .enumerate()
-                .map(|(i, &name)| match layout.field(self, i) {
-                    Err(err) => {
-                        bug!("no layout found for field {}: `{:?}`", name, err);
+                .map(|(i, &name)| {
+                    let field_layout = layout.field(self, i);
+                    let offset = layout.fields.offset(i);
+                    let field_end = offset + field_layout.size;
+                    if min_size < field_end {
+                        min_size = field_end;
                     }
-                    Ok(field_layout) => {
-                        let offset = layout.fields.offset(i);
-                        let field_end = offset + field_layout.size;
-                        if min_size < field_end {
-                            min_size = field_end;
-                        }
-                        FieldInfo {
-                            name: name.to_string(),
-                            offset: offset.bytes(),
-                            size: field_layout.size.bytes(),
-                            align: field_layout.align.abi.bytes(),
-                        }
+                    FieldInfo {
+                        name: name.to_string(),
+                        offset: offset.bytes(),
+                        size: field_layout.size.bytes(),
+                        align: field_layout.align.abi.bytes(),
                     }
                 })
                 .collect();
@@ -1885,7 +1907,7 @@ pub fn compute(
                 let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
                 match tail.kind() {
                     ty::Param(_) | ty::Projection(_) => {
-                        debug_assert!(tail.has_param_types_or_consts());
+                        debug_assert!(tail.definitely_has_param_types_or_consts(tcx));
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
                     _ => bug!(
@@ -1995,17 +2017,33 @@ pub trait HasParamEnv<'tcx> {
 }
 
 impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
+    #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         &self.data_layout
     }
 }
 
 impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
+    #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         *self
     }
 }
 
+impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        &self.data_layout
+    }
+}
+
+impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
+    #[inline]
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        **self
+    }
+}
+
 impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> {
     fn param_env(&self) -> ty::ParamEnv<'tcx> {
         self.param_env
@@ -2024,91 +2062,121 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
-pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
+pub trait MaybeResult<T> {
+    type Error;
 
-impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+    fn from(x: Result<T, Self::Error>) -> Self;
+    fn to_result(self) -> Result<T, Self::Error>;
+}
 
-    /// Computes the layout of a type. Note that this implicitly
-    /// executes in "reveal all" mode.
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        let param_env = self.param_env.with_reveal_all_normalized(self.tcx);
-        let ty = self.tcx.normalize_erasing_regions(param_env, ty);
-        let layout = self.tcx.layout_raw(param_env.and(ty))?;
-        let layout = TyAndLayout { ty, layout };
-
-        // N.B., this recording is normally disabled; when enabled, it
-        // can however trigger recursive invocations of `layout_of`.
-        // Therefore, we execute it *after* the main query has
-        // completed, to avoid problems around recursive structures
-        // and the like. (Admittedly, I wasn't able to reproduce a problem
-        // here, but it seems like the right thing to do. -nmatsakis)
-        self.record_layout_for_printing(layout);
+impl<T> MaybeResult<T> for T {
+    type Error = !;
 
-        Ok(layout)
+    fn from(Ok(x): Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        Ok(self)
     }
 }
 
-impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<T, E> MaybeResult<T> for Result<T, E> {
+    type Error = E;
 
-    /// Computes the layout of a type. Note that this implicitly
-    /// executes in "reveal all" mode.
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        let param_env = self.param_env.with_reveal_all_normalized(*self.tcx);
-        let ty = self.tcx.normalize_erasing_regions(param_env, ty);
-        let layout = self.tcx.layout_raw(param_env.and(ty))?;
-        let layout = TyAndLayout { ty, layout };
-
-        // N.B., this recording is normally disabled; when enabled, it
-        // can however trigger recursive invocations of `layout_of`.
-        // Therefore, we execute it *after* the main query has
-        // completed, to avoid problems around recursive structures
-        // and the like. (Admittedly, I wasn't able to reproduce a problem
-        // here, but it seems like the right thing to do. -nmatsakis)
-        let cx = LayoutCx { tcx: *self.tcx, param_env: self.param_env };
-        cx.record_layout_for_printing(layout);
+    fn from(x: Result<T, Self::Error>) -> Self {
+        x
+    }
+    fn to_result(self) -> Result<T, Self::Error> {
+        self
+    }
+}
 
-        Ok(layout)
+pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
+
+/// Trait for contexts that want to be able to compute layouts of types.
+/// This automatically gives access to `LayoutOf`, through a blanket `impl`.
+pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
+    /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
+    /// returned from `layout_of` (see also `handle_layout_err`).
+    type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
+
+    /// `Span` to use for `tcx.at(span)`, from `layout_of`.
+    // FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
+    #[inline]
+    fn layout_tcx_at_span(&self) -> Span {
+        DUMMY_SP
     }
+
+    /// Helper used for `layout_of`, to adapt `tcx.layout_of(...)` into a
+    /// `Self::LayoutOfResult` (which does not need to be a `Result<...>`).
+    ///
+    /// Most `impl`s, which propagate `LayoutError`s, should simply return `err`,
+    /// but this hook allows e.g. codegen to return only `TyAndLayout` from its
+    /// `cx.layout_of(...)`, without any `Result<...>` around it to deal with
+    /// (and any `LayoutError`s are turned into fatal errors or ICEs).
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        span: Span,
+        ty: Ty<'tcx>,
+    ) -> <Self::LayoutOfResult as MaybeResult<TyAndLayout<'tcx>>>::Error;
 }
 
-// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
-impl TyCtxt<'tcx> {
+/// Blanket extension trait for contexts that can compute layouts of types.
+pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> {
     /// Computes the layout of a type. Note that this implicitly
-    /// executes in "reveal all" mode.
+    /// executes in "reveal all" mode, and will normalize the input type.
+    #[inline]
+    fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
+        self.spanned_layout_of(ty, DUMMY_SP)
+    }
+
+    /// Computes the layout of a type, at `span`. Note that this implicitly
+    /// executes in "reveal all" mode, and will normalize the input type.
+    // FIXME(eddyb) avoid passing information like this, and instead add more
+    // `TyCtxt::at`-like APIs to be able to do e.g. `cx.at(span).layout_of(ty)`.
     #[inline]
-    pub fn layout_of(
-        self,
-        param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-    ) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
-        let cx = LayoutCx { tcx: self, param_env: param_env_and_ty.param_env };
-        cx.layout_of(param_env_and_ty.value)
+    fn spanned_layout_of(&self, ty: Ty<'tcx>, span: Span) -> Self::LayoutOfResult {
+        let span = if !span.is_dummy() { span } else { self.layout_tcx_at_span() };
+        MaybeResult::from(
+            self.tcx()
+                .at(span)
+                .layout_of(self.param_env().and(ty))
+                .map_err(|err| self.handle_layout_err(err, span, ty)),
+        )
     }
 }
 
-impl ty::query::TyCtxtAt<'tcx> {
-    /// Computes the layout of a type. Note that this implicitly
-    /// executes in "reveal all" mode.
+impl<C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {}
+
+impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+
     #[inline]
-    pub fn layout_of(
-        self,
-        param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-    ) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
-        let cx = LayoutCx { tcx: self.at(self.span), param_env: param_env_and_ty.param_env };
-        cx.layout_of(param_env_and_ty.value)
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
-impl<'tcx, C> TyAndLayoutMethods<'tcx, C> for Ty<'tcx>
+impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+
+    #[inline]
+    fn layout_tcx_at_span(&self) -> Span {
+        self.tcx.span
+    }
+
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
+    }
+}
+
+impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx>
 where
-    C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
+    C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
 {
-    fn for_variant(
+    fn ty_and_layout_for_variant(
         this: TyAndLayout<'tcx>,
         cx: &C,
         variant_index: VariantIdx,
@@ -2125,8 +2193,11 @@ fn for_variant(
             }
 
             Variants::Single { index } => {
+                let tcx = cx.tcx();
+                let param_env = cx.param_env();
+
                 // Deny calling for_variant more than once for non-Single enums.
-                if let Ok(original_layout) = cx.layout_of(this.ty).to_result() {
+                if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) {
                     assert_eq!(original_layout.variants, Variants::Single { index });
                 }
 
@@ -2136,7 +2207,6 @@ fn for_variant(
                     ty::Adt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!(),
                 };
-                let tcx = cx.tcx();
                 tcx.intern_layout(Layout {
                     variants: Variants::Single { index: variant_index },
                     fields: match NonZeroUsize::new(fields) {
@@ -2158,32 +2228,24 @@ fn for_variant(
         TyAndLayout { ty: this.ty, layout }
     }
 
-    fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
-        enum TyMaybeWithLayout<C: LayoutOf> {
-            Ty(C::Ty),
-            TyAndLayout(C::TyAndLayout),
+    fn ty_and_layout_field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> TyAndLayout<'tcx> {
+        enum TyMaybeWithLayout<'tcx> {
+            Ty(Ty<'tcx>),
+            TyAndLayout(TyAndLayout<'tcx>),
         }
 
-        fn ty_and_layout_kind<
-            C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
-                + HasTyCtxt<'tcx>
-                + HasParamEnv<'tcx>,
-        >(
+        fn field_ty_or_layout(
             this: TyAndLayout<'tcx>,
-            cx: &C,
+            cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
             i: usize,
-            ty: C::Ty,
-        ) -> TyMaybeWithLayout<C> {
+        ) -> TyMaybeWithLayout<'tcx> {
             let tcx = cx.tcx();
-            let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
+            let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> {
                 let layout = Layout::scalar(cx, tag.clone());
-                MaybeResult::from(Ok(TyAndLayout {
-                    layout: tcx.intern_layout(layout),
-                    ty: tag.value.to_ty(tcx),
-                }))
+                TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
             };
 
-            match *ty.kind() {
+            match *this.ty.kind() {
                 ty::Bool
                 | ty::Char
                 | ty::Int(_)
@@ -2194,7 +2256,7 @@ fn ty_and_layout_kind<
                 | ty::FnDef(..)
                 | ty::GeneratorWitness(..)
                 | ty::Foreign(..)
-                | ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
+                | ty::Dynamic(..) => bug!("TyAndLayout::field({:?}): not applicable", this),
 
                 // Potentially-fat pointers.
                 ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
@@ -2206,17 +2268,19 @@ fn ty_and_layout_kind<
                     // as the `Abi` or `FieldsShape` is checked by users.
                     if i == 0 {
                         let nil = tcx.mk_unit();
-                        let ptr_ty = if ty.is_unsafe_ptr() {
+                        let unit_ptr_ty = if this.ty.is_unsafe_ptr() {
                             tcx.mk_mut_ptr(nil)
                         } else {
                             tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
                         };
-                        return TyMaybeWithLayout::TyAndLayout(MaybeResult::from(
-                            cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
-                                ptr_layout.ty = ty;
-                                ptr_layout
-                            }),
-                        ));
+
+                        // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
+                        // the `Result` should always work because the type is
+                        // always either `*mut ()` or `&'static mut ()`.
+                        return TyMaybeWithLayout::TyAndLayout(TyAndLayout {
+                            ty: this.ty,
+                            ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+                        });
                     }
 
                     match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
@@ -2240,7 +2304,7 @@ fn ty_and_layout_kind<
                             ])
                             */
                         }
-                        _ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
+                        _ => bug!("TyAndLayout::field({:?}): not applicable", this),
                     }
                 }
 
@@ -2249,9 +2313,11 @@ fn ty_and_layout_kind<
                 ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
 
                 // Tuples, generators and closures.
-                ty::Closure(_, ref substs) => {
-                    ty_and_layout_kind(this, cx, i, substs.as_closure().tupled_upvars_ty())
-                }
+                ty::Closure(_, ref substs) => field_ty_or_layout(
+                    TyAndLayout { ty: substs.as_closure().tupled_upvars_ty(), ..this },
+                    cx,
+                    i,
+                ),
 
                 ty::Generator(def_id, ref substs, _) => match this.variants {
                     Variants::Single { index } => TyMaybeWithLayout::Ty(
@@ -2294,24 +2360,42 @@ fn ty_and_layout_kind<
                 | ty::Opaque(..)
                 | ty::Param(_)
                 | ty::Infer(_)
-                | ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
+                | ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
             }
         }
 
-        cx.layout_of(match ty_and_layout_kind(this, cx, i, this.ty) {
-            TyMaybeWithLayout::Ty(result) => result,
-            TyMaybeWithLayout::TyAndLayout(result) => return result,
-        })
+        match field_ty_or_layout(this, cx, i) {
+            TyMaybeWithLayout::Ty(field_ty) => {
+                cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
+                    bug!(
+                        "failed to get layout for `{}`: {},\n\
+                         despite it being a field (#{}) of an existing layout: {:#?}",
+                        field_ty,
+                        e,
+                        i,
+                        this
+                    )
+                })
+            }
+            TyMaybeWithLayout::TyAndLayout(field_layout) => field_layout,
+        }
     }
 
-    fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<PointeeInfo> {
+    fn ty_and_layout_pointee_info_at(
+        this: TyAndLayout<'tcx>,
+        cx: &C,
+        offset: Size,
+    ) -> Option<PointeeInfo> {
+        let tcx = cx.tcx();
+        let param_env = cx.param_env();
+
         let addr_space_of_ty = |ty: Ty<'tcx>| {
             if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
         };
 
         let pointee_info = match *this.ty.kind() {
             ty::RawPtr(mt) if offset.bytes() == 0 => {
-                cx.layout_of(mt.ty).to_result().ok().map(|layout| PointeeInfo {
+                tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: None,
@@ -2319,18 +2403,15 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
                 })
             }
             ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
-                cx.layout_of(cx.tcx().mk_fn_ptr(fn_sig)).to_result().ok().map(|layout| {
-                    PointeeInfo {
-                        size: layout.size,
-                        align: layout.align.abi,
-                        safe: None,
-                        address_space: cx.data_layout().instruction_address_space,
-                    }
+                tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo {
+                    size: layout.size,
+                    align: layout.align.abi,
+                    safe: None,
+                    address_space: cx.data_layout().instruction_address_space,
                 })
             }
             ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
                 let address_space = addr_space_of_ty(ty);
-                let tcx = cx.tcx();
                 let kind = if tcx.sess.opts.optimize == OptLevel::No {
                     // Use conservative pointer kind if not optimizing. This saves us the
                     // Freeze/Unpin queries, and can save time in the codegen backend (noalias
@@ -2359,7 +2440,7 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
                     }
                 };
 
-                cx.layout_of(ty).to_result().ok().map(|layout| PointeeInfo {
+                tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
                     size: layout.size,
                     align: layout.align.abi,
                     safe: Some(kind),
@@ -2447,6 +2528,7 @@ fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<Poin
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for LayoutError<'tcx> {
+    #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
         use crate::ty::layout::LayoutError::*;
         mem::discriminant(self).hash_stable(hcx, hasher);
@@ -2474,10 +2556,9 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
                 // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
                 // track of a polymorphization `ParamEnv` to allow normalizing later.
                 let mut sig = match *ty.kind() {
-                    ty::FnDef(def_id, substs) if tcx.sess.opts.debugging_opts.polymorphize => tcx
+                    ty::FnDef(def_id, substs) => tcx
                         .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id))
                         .subst(tcx, substs),
-                    ty::FnDef(def_id, substs) => tcx.fn_sig(def_id).subst(tcx, substs),
                     _ => unreachable!(),
                 };
 
@@ -2562,11 +2643,7 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
 
 pub trait FnAbiExt<'tcx, C>
 where
-    C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
-        + HasDataLayout
-        + HasTargetSpec
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
+    C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
 {
     /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
     ///
@@ -2638,6 +2715,7 @@ fn new_internal(
 /// compiled with `-Cpanic=unwind` and referenced from another crate compiled
 /// with `-Cpanic=abort` will look like they can't unwind when in fact they
 /// might (from a foreign exception or similar).
+#[inline]
 pub fn fn_can_unwind(
     tcx: TyCtxt<'tcx>,
     codegen_fn_attr_flags: CodegenFnAttrFlags,
@@ -2713,6 +2791,7 @@ pub fn fn_can_unwind(
     }
 }
 
+#[inline]
 pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
     use rustc_target::spec::abi::Abi::*;
     match tcx.sess.target.adjust_abi(abi) {
@@ -2747,11 +2826,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
 
 impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
 where
-    C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
-        + HasDataLayout
-        + HasTargetSpec
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
+    C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
 {
     fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
         call::FnAbi::new_internal(cx, sig, extra_args, None, CodegenFnAttrFlags::empty(), false)
@@ -2846,10 +2921,8 @@ fn new_internal(
                 return;
             }
 
-            if scalar.valid_range.start() < scalar.valid_range.end() {
-                if *scalar.valid_range.start() > 0 {
-                    attrs.set(ArgAttribute::NonNull);
-                }
+            if !scalar.valid_range.contains_zero() {
+                attrs.set(ArgAttribute::NonNull);
             }
 
             if let Some(pointee) = layout.pointee_info_at(cx, offset) {
@@ -3028,16 +3101,15 @@ fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
     }
 }
 
-fn make_thin_self_ptr<'tcx, C>(cx: &C, mut layout: TyAndLayout<'tcx>) -> TyAndLayout<'tcx>
-where
-    C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
-        + HasTyCtxt<'tcx>
-        + HasParamEnv<'tcx>,
-{
+fn make_thin_self_ptr<'tcx>(
+    cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
+    layout: TyAndLayout<'tcx>,
+) -> TyAndLayout<'tcx> {
+    let tcx = cx.tcx();
     let fat_pointer_ty = if layout.is_unsized() {
         // unsized `self` is passed as a pointer to `self`
         // FIXME (mikeyhew) change this to use &own if it is ever added to the language
-        cx.tcx().mk_mut_ptr(layout.ty)
+        tcx.mk_mut_ptr(layout.ty)
     } else {
         match layout.abi {
             Abi::ScalarPair(..) => (),
@@ -3071,8 +3143,13 @@ fn make_thin_self_ptr<'tcx, C>(cx: &C, mut layout: TyAndLayout<'tcx>) -> TyAndLa
     // we now have a type like `*mut RcBox<dyn Trait>`
     // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
     // this is understood as a special case elsewhere in the compiler
-    let unit_pointer_ty = cx.tcx().mk_mut_ptr(cx.tcx().mk_unit());
-    layout = cx.layout_of(unit_pointer_ty);
-    layout.ty = fat_pointer_ty;
-    layout
+    let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit());
+
+    TyAndLayout {
+        ty: fat_pointer_ty,
+
+        // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
+        // should always work because the type is always `*mut ()`.
+        ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+    }
 }
index 62e093581b8622322b0604546e028ead7251e4f9..d01ca27b8511895b78102b6c087c1cd496e33fb1 100644 (file)
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
-use rustc_hir::{Constness, Node};
+use rustc_hir::Node;
 use rustc_macros::HashStable;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::Align;
 
 use std::cmp::Ordering;
+use std::collections::BTreeMap;
 use std::hash::{Hash, Hasher};
 use std::ops::ControlFlow;
 use std::{fmt, ptr, str};
@@ -132,6 +133,10 @@ pub struct ResolverOutputs {
     /// via `extern crate` item and not `--extern` option or compiler built-in.
     pub extern_prelude: FxHashMap<Symbol, bool>,
     pub main_def: Option<MainDefinition>,
+    pub trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
+    /// A list of proc macro LocalDefIds, written out in the order in which
+    /// they are declared in the static array generated by proc_macro_harness.
+    pub proc_macros: Vec<LocalDefId>,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -181,6 +186,25 @@ pub enum Visibility {
     Invisible,
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
+pub enum BoundConstness {
+    /// `T: Trait`
+    NotConst,
+    /// `T: ~const Trait`
+    ///
+    /// Requires resolving to const only when we are in a const context.
+    ConstIfConst,
+}
+
+impl fmt::Display for BoundConstness {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotConst => f.write_str("normal"),
+            Self::ConstIfConst => f.write_str("`~const`"),
+        }
+    }
+}
+
 #[derive(
     Clone,
     Debug,
@@ -457,10 +481,6 @@ pub enum PredicateKind<'tcx> {
     /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
     /// would be the type parameters.
-    ///
-    /// A trait predicate will have `Constness::Const` if it originates
-    /// from a bound on a `const fn` without the `?const` opt-out (e.g.,
-    /// `const fn foobar<Foo: Bar>() {}`).
     Trait(TraitPredicate<'tcx>),
 
     /// `where 'a: 'b`
@@ -502,7 +522,7 @@ pub enum PredicateKind<'tcx> {
     Coerce(CoercePredicate<'tcx>),
 
     /// Constant initializer must evaluate successfully.
-    ConstEvaluatable(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+    ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
 
     /// Constants must be equal. The first component is the const that is expected.
     ConstEquate(&'tcx Const<'tcx>, &'tcx Const<'tcx>),
@@ -632,10 +652,7 @@ pub fn subst_supertrait(
 pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>,
 
-    /// A trait predicate will have `Constness::Const` if it originates
-    /// from a bound on a `const fn` without the `?const` opt-out (e.g.,
-    /// `const fn foobar<Foo: Bar>() {}`).
-    pub constness: hir::Constness,
+    pub constness: BoundConstness,
 }
 
 pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
@@ -1292,7 +1309,7 @@ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
             Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
 
             Reveal::All => {
-                if value.is_global() {
+                if value.is_known_global() {
                     ParamEnvAnd { param_env: self.without_caller_bounds(), value }
                 } else {
                     ParamEnvAnd { param_env: self, value }
@@ -1304,7 +1321,7 @@ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
 pub struct ConstnessAnd<T> {
-    pub constness: Constness,
+    pub constness: BoundConstness,
     pub value: T,
 }
 
@@ -1312,18 +1329,18 @@ pub struct ConstnessAnd<T> {
 // the constness of trait bounds is being propagated correctly.
 pub trait WithConstness: Sized {
     #[inline]
-    fn with_constness(self, constness: Constness) -> ConstnessAnd<Self> {
+    fn with_constness(self, constness: BoundConstness) -> ConstnessAnd<Self> {
         ConstnessAnd { constness, value: self }
     }
 
     #[inline]
-    fn with_const(self) -> ConstnessAnd<Self> {
-        self.with_constness(Constness::Const)
+    fn with_const_if_const(self) -> ConstnessAnd<Self> {
+        self.with_constness(BoundConstness::ConstIfConst)
     }
 
     #[inline]
     fn without_const(self) -> ConstnessAnd<Self> {
-        self.with_constness(Constness::NotConst)
+        self.with_constness(BoundConstness::NotConst)
     }
 }
 
@@ -1665,16 +1682,12 @@ pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir().krate().body_ids.iter()`.
     pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + Captures<'tcx> + 'tcx {
-        self.hir()
-            .krate()
-            .body_ids
-            .iter()
-            .map(move |&body_id| self.hir().body_owner_def_id(body_id))
+        self.hir().krate().bodies.keys().map(move |&body_id| self.hir().body_owner_def_id(body_id))
     }
 
     pub fn par_body_owners<F: Fn(LocalDefId) + sync::Sync + sync::Send>(self, f: F) {
-        par_iter(&self.hir().krate().body_ids)
-            .for_each(|&body_id| f(self.hir().body_owner_def_id(body_id)));
+        par_iter(&self.hir().krate().bodies)
+            .for_each(|(&body_id, _)| f(self.hir().body_owner_def_id(body_id)));
     }
 
     pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator<Item = &'tcx AssocItem> {
index 86750d5c081113e9126d6745cc74adfcd81efa15..ef4ad998f10c81ab2f2ec3745e31d5e5c7a2f9c8 100644 (file)
@@ -194,7 +194,7 @@ fn compute_components_recursive(
     out: &mut SmallVec<[Component<'tcx>; 4]>,
     visited: &mut SsoHashSet<GenericArg<'tcx>>,
 ) {
-    for child in parent.walk_shallow(visited) {
+    for child in parent.walk_shallow(tcx, visited) {
         match child.unpack() {
             GenericArgKind::Type(ty) => {
                 compute_components(tcx, ty, out, visited);
index 8558d6bb00e724a79dbf9cde7985a7a3aac5e538..db4a1d94d1a7c28bf8f180763fe0182ab39fda34 100644 (file)
@@ -927,20 +927,21 @@ macro_rules! print_underscore {
         }
 
         match ct.val {
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                if let Some(promoted) = promoted {
-                    p!(print_value_path(def.did, substs));
+            ty::ConstKind::Unevaluated(uv) => {
+                if let Some(promoted) = uv.promoted {
+                    let substs = uv.substs_.unwrap();
+                    p!(print_value_path(uv.def.did, substs));
                     p!(write("::{:?}", promoted));
                 } else {
-                    match self.tcx().def_kind(def.did) {
+                    let tcx = self.tcx();
+                    match tcx.def_kind(uv.def.did) {
                         DefKind::Static | DefKind::Const | DefKind::AssocConst => {
-                            p!(print_value_path(def.did, substs))
+                            p!(print_value_path(uv.def.did, uv.substs(tcx)))
                         }
                         _ => {
-                            if def.is_local() {
-                                let span = self.tcx().def_span(def.did);
-                                if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span)
-                                {
+                            if uv.def.is_local() {
+                                let span = tcx.def_span(uv.def.did);
+                                if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) {
                                     p!(write("{}", snip))
                                 } else {
                                     print_underscore!()
@@ -1192,7 +1193,7 @@ fn pretty_print_const_value(
 
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
             //
-            // NB: the `has_param_types_or_consts` check ensures that we can use
+            // NB: the `potentially_has_param_types_or_consts` check ensures that we can use
             // the `destructure_const` query with an empty `ty::ParamEnv` without
             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
@@ -1200,7 +1201,9 @@ fn pretty_print_const_value(
             //
             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
             // correct `ty::ParamEnv` to allow printing *all* constant values.
-            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
+                if !ty.potentially_has_param_types_or_consts() =>
+            {
                 let contents = self.tcx().destructure_const(
                     ty::ParamEnv::reveal_all()
                         .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
@@ -1218,13 +1221,20 @@ fn pretty_print_const_value(
                         }
                         p!(")");
                     }
-                    ty::Adt(def, substs) if def.variants.is_empty() => {
-                        p!(print_value_path(def.did, substs));
+                    ty::Adt(def, _) if def.variants.is_empty() => {
+                        self = self.typed_value(
+                            |mut this| {
+                                write!(this, "unreachable()")?;
+                                Ok(this)
+                            },
+                            |this| this.print_type(ty),
+                            ": ",
+                        )?;
                     }
                     ty::Adt(def, substs) => {
-                        let variant_id =
-                            contents.variant.expect("destructed const of adt without variant id");
-                        let variant_def = &def.variants[variant_id];
+                        let variant_idx =
+                            contents.variant.expect("destructed const of adt without variant idx");
+                        let variant_def = &def.variants[variant_idx];
                         p!(print_value_path(variant_def.def_id, substs));
 
                         match variant_def.ctor_kind {
@@ -2015,6 +2025,7 @@ fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
         debug!("prepare_late_bound_region_info(value: {:?})", value);
 
         struct LateBoundRegionNameCollector<'a, 'tcx> {
+            tcx: TyCtxt<'tcx>,
             used_region_names: &'a mut FxHashSet<Symbol>,
             type_collector: SsoHashSet<Ty<'tcx>>,
         }
@@ -2022,6 +2033,10 @@ struct LateBoundRegionNameCollector<'a, 'tcx> {
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
             type BreakTy = ();
 
+            fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                Some(self.tcx)
+            }
+
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
                 debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
@@ -2051,6 +2066,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
 
         self.used_region_names.clear();
         let mut collector = LateBoundRegionNameCollector {
+            tcx: self.tcx,
             used_region_names: &mut self.used_region_names,
             type_collector: SsoHashSet::new(),
         };
@@ -2285,8 +2301,8 @@ pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPat
                 print_value_path(closure_def_id, &[]),
                 write("` implements the trait `{}`", kind))
             }
-            ty::PredicateKind::ConstEvaluatable(def, substs) => {
-                p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
+            ty::PredicateKind::ConstEvaluatable(uv) => {
+                p!("the constant `", print_value_path(uv.def.did, uv.substs_.map_or(&[], |x| x)), "` can be evaluated")
             }
             ty::PredicateKind::ConstEquate(c1, c2) => {
                 p!("the constant `", print(c1), "` equals `", print(c2), "`")
index 9c48f05617e0993e09883a8ff5b3ef2123644a42..9d1be212f5b8c49771a62de47cc48263bc8032f7 100644 (file)
@@ -200,12 +200,12 @@ fn relate<R: TypeRelation<'tcx>>(
     }
 }
 
-impl<'tcx> Relate<'tcx> for ast::Constness {
+impl<'tcx> Relate<'tcx> for ty::BoundConstness {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
-        a: ast::Constness,
-        b: ast::Constness,
-    ) -> RelateResult<'tcx, ast::Constness> {
+        a: ty::BoundConstness,
+        b: ty::BoundConstness,
+    ) -> RelateResult<'tcx, ty::BoundConstness> {
         if a != b {
             Err(TypeError::ConstnessMismatch(expected_found(relation, a, b)))
         } else {
@@ -577,13 +577,13 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         }
 
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
-            if tcx.features().const_evaluatable_checked =>
+            if tcx.features().generic_const_exprs =>
         {
-            tcx.try_unify_abstract_consts(((au.def, au.substs), (bu.def, bu.substs)))
+            tcx.try_unify_abstract_consts((au.shrink(), bu.shrink()))
         }
 
         // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
-        // and is the better alternative to waiting until `const_evaluatable_checked` can
+        // and is the better alternative to waiting until `generic_const_exprs` can
         // be stabilized.
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if au.def == bu.def && au.promoted == bu.promoted =>
@@ -591,13 +591,13 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
             let substs = relation.relate_with_variance(
                 ty::Variance::Invariant,
                 ty::VarianceDiagInfo::default(),
-                au.substs,
-                bu.substs,
+                au.substs(tcx),
+                bu.substs(tcx),
             )?;
             return Ok(tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: au.def,
-                    substs,
+                    substs_: Some(substs),
                     promoted: au.promoted,
                 }),
                 ty: a.ty,
index a46cac1e7f7f55e55348909df62e8c6716d64dab..89ad99d9f0794f6d9f7805a4d7c96bd86dbdf7c5 100644 (file)
@@ -8,7 +8,6 @@
 use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
 use crate::ty::{self, InferConst, Lift, Ty, TyCtxt};
 use rustc_data_structures::functor::IdFunctor;
-use rustc_hir as hir;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::CRATE_DEF_INDEX;
 use rustc_index::vec::{Idx, IndexVec};
@@ -155,8 +154,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl fmt::Debug for ty::TraitPredicate<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if let hir::Constness::Const = self.constness {
-            write!(f, "const ")?;
+        if let ty::BoundConstness::ConstIfConst = self.constness {
+            write!(f, "~const ")?;
         }
         write!(f, "TraitPredicate({:?})", self.trait_ref)
     }
@@ -190,8 +189,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
                 write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
             }
-            ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
-                write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs)
+            ty::PredicateKind::ConstEvaluatable(uv) => {
+                write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs_)
             }
             ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
             ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -241,6 +240,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     crate::traits::Reveal,
     crate::ty::adjustment::AutoBorrowMutability,
     crate::ty::AdtKind,
+    crate::ty::BoundConstness,
     // Including `BoundRegionKind` is a *bit* dubious, but direct
     // references to bound region appear in `ty::Error`, and aren't
     // really meant to be folded. In general, we can only fold a fully
@@ -447,8 +447,8 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
             ty::PredicateKind::ObjectSafe(trait_def_id) => {
                 Some(ty::PredicateKind::ObjectSafe(trait_def_id))
             }
-            ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
-                tcx.lift(substs).map(|substs| ty::PredicateKind::ConstEvaluatable(def_id, substs))
+            ty::PredicateKind::ConstEvaluatable(uv) => {
+                tcx.lift(uv).map(|uv| ty::PredicateKind::ConstEvaluatable(uv))
             }
             ty::PredicateKind::ConstEquate(c1, c2) => {
                 tcx.lift((c1, c2)).map(|(c1, c2)| ty::PredicateKind::ConstEquate(c1, c2))
@@ -974,6 +974,10 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::Br
 }
 
 impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
+    fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+        folder.fold_predicate(self)
+    }
+
     fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
         let new = self.inner.kind.fold_with(folder);
         folder.tcx().reuse_or_mk_predicate(self, new)
@@ -1046,13 +1050,7 @@ fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
         match self {
             ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)),
             ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)),
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                ty::ConstKind::Unevaluated(ty::Unevaluated {
-                    def,
-                    substs: substs.fold_with(folder),
-                    promoted,
-                })
-            }
+            ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)),
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(..)
@@ -1064,7 +1062,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow
         match *self {
             ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
             ty::ConstKind::Param(p) => p.visit_with(visitor),
-            ty::ConstKind::Unevaluated(ct) => ct.substs.visit_with(visitor),
+            ty::ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
             ty::ConstKind::Value(_)
             | ty::ConstKind::Bound(..)
             | ty::ConstKind::Placeholder(_)
@@ -1082,3 +1080,53 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlo
         ControlFlow::CONTINUE
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+        ty::Unevaluated {
+            def: self.def,
+            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            promoted: self.promoted,
+        }
+    }
+
+    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        visitor.visit_unevaluated_const(*self)
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
+            self.substs(tcx).visit_with(visitor)
+        } else if let Some(substs) = self.substs_ {
+            substs.visit_with(visitor)
+        } else {
+            debug!("ignoring default substs of `{:?}`", self.def);
+            ControlFlow::CONTINUE
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
+    fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
+        ty::Unevaluated {
+            def: self.def,
+            substs_: Some(self.substs(folder.tcx()).fold_with(folder)),
+            promoted: self.promoted,
+        }
+    }
+
+    fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        visitor.visit_unevaluated_const(self.expand())
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+        if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
+            self.substs(tcx).visit_with(visitor)
+        } else if let Some(substs) = self.substs_ {
+            substs.visit_with(visitor)
+        } else {
+            debug!("ignoring default substs of `{:?}`", self.def);
+            ControlFlow::CONTINUE
+        }
+    }
+}
index 8e0a2d4a28df026167d7fada4d7c6083ea5bd951..65dd61b63295cf2eef68df4c1a982057a952eb93 100644 (file)
@@ -878,7 +878,7 @@ pub fn def_id(&self) -> DefId {
     pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
         self.map_bound(|trait_ref| ty::TraitPredicate {
             trait_ref,
-            constness: hir::Constness::NotConst,
+            constness: ty::BoundConstness::NotConst,
         })
     }
 }
@@ -1565,26 +1565,26 @@ pub fn type_flags(&self) -> TypeFlags {
 
         match *self {
             ty::ReVar(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
             }
             ty::RePlaceholder(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
             }
             ty::ReEarlyBound(..) => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
-                flags = flags | TypeFlags::HAS_RE_PARAM;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM;
             }
             ty::ReFree { .. } => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
             }
             ty::ReEmpty(_) | ty::ReStatic => {
-                flags = flags | TypeFlags::HAS_FREE_REGIONS;
+                flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
             }
             ty::ReLateBound(..) => {
                 flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
index 4fbb4d1806f83fb774c2cac1d62789bc4a8ba633..2438d1a16021b50aa4f318d5946842e6bc6d4281 100644 (file)
@@ -234,7 +234,7 @@ pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) ->
         })
     }
 
-    fn fill_item<F>(
+    pub fn fill_item<F>(
         substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         tcx: TyCtxt<'tcx>,
         defs: &ty::Generics,
@@ -249,7 +249,7 @@ fn fill_item<F>(
         Self::fill_single(substs, defs, mk_kind)
     }
 
-    fn fill_single<F>(
+    pub fn fill_single<F>(
         substs: &mut SmallVec<[GenericArg<'tcx>; 8]>,
         defs: &ty::Generics,
         mk_kind: &mut F,
@@ -486,7 +486,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_subst() {
+        if !t.potentially_needs_subst() {
             return t;
         }
 
@@ -497,10 +497,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
     }
 
     fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if !c.needs_subst() {
-            return c;
-        }
-
         if let ty::ConstKind::Param(p) = c.val {
             self.const_for_param(p, c)
         } else {
index a78206034f08a50206d657980e4469f13641749b..1b8e94260b9b5d73f0228dc5cf7b1aaffd5d262d 100644 (file)
@@ -225,14 +225,12 @@ pub fn struct_tail_with_normalize(
                     }
                 }
 
-                ty::Tuple(tys) => {
-                    if let Some((&last_ty, _)) = tys.split_last() {
-                        ty = last_ty.expect_ty();
-                    } else {
-                        break;
-                    }
+                ty::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => {
+                    ty = last_ty.expect_ty();
                 }
 
+                ty::Tuple(_) => break,
+
                 ty::Projection(_) | ty::Opaque(..) => {
                     let normalized = normalize(ty);
                     if ty == normalized {
index c2fe5f1ef3f625975eed1ae231d5a5dfa11c8cfe..73985cf31e0f9e736c79d67faa3d440cfee8850d 100644 (file)
@@ -1,8 +1,8 @@
 //! An iterator over the type substructure.
 //! WARNING: this does not keep track of the region depth.
 
-use crate::ty;
 use crate::ty::subst::{GenericArg, GenericArgKind};
+use crate::ty::{self, TyCtxt};
 use rustc_data_structures::sso::SsoHashSet;
 use smallvec::{self, SmallVec};
 
@@ -11,6 +11,7 @@
 type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
 
 pub struct TypeWalker<'tcx> {
+    expose_default_const_substs: Option<TyCtxt<'tcx>>,
     stack: TypeWalkerStack<'tcx>,
     last_subtree: usize,
     pub visited: SsoHashSet<GenericArg<'tcx>>,
@@ -25,8 +26,13 @@ pub struct TypeWalker<'tcx> {
 /// It maintains a set of visited types and
 /// skips any types that are already there.
 impl<'tcx> TypeWalker<'tcx> {
-    pub fn new(root: GenericArg<'tcx>) -> Self {
-        Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() }
+    fn new(expose_default_const_substs: Option<TyCtxt<'tcx>>, root: GenericArg<'tcx>) -> Self {
+        Self {
+            expose_default_const_substs,
+            stack: smallvec![root],
+            last_subtree: 1,
+            visited: SsoHashSet::new(),
+        }
     }
 
     /// Skips the subtree corresponding to the last type
@@ -55,7 +61,7 @@ fn next(&mut self) -> Option<GenericArg<'tcx>> {
             let next = self.stack.pop()?;
             self.last_subtree = self.stack.len();
             if self.visited.insert(next) {
-                push_inner(&mut self.stack, next);
+                push_inner(self.expose_default_const_substs, &mut self.stack, next);
                 debug!("next: stack={:?}", self.stack);
                 return Some(next);
             }
@@ -74,8 +80,8 @@ impl GenericArg<'tcx> {
     /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
     /// [isize] => { [isize], isize }
     /// ```
-    pub fn walk(self) -> TypeWalker<'tcx> {
-        TypeWalker::new(self)
+    pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
+        TypeWalker::new(Some(tcx), self)
     }
 
     /// Iterator that walks the immediate children of `self`. Hence
@@ -87,16 +93,21 @@ pub fn walk(self) -> TypeWalker<'tcx> {
     /// and skips any types that are already there.
     pub fn walk_shallow(
         self,
+        tcx: TyCtxt<'tcx>,
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> impl Iterator<Item = GenericArg<'tcx>> {
         let mut stack = SmallVec::new();
-        push_inner(&mut stack, self);
+        push_inner(Some(tcx), &mut stack, self);
         stack.retain(|a| visited.insert(*a));
         stack.into_iter()
     }
 }
 
 impl<'tcx> super::TyS<'tcx> {
+    pub fn walk_ignoring_default_const_substs(&'tcx self) -> TypeWalker<'tcx> {
+        TypeWalker::new(None, self.into())
+    }
+
     /// Iterator that walks `self` and any types reachable from
     /// `self`, in depth-first order. Note that just walks the types
     /// that appear in `self`, it does not descend into the fields of
@@ -107,18 +118,22 @@ impl<'tcx> super::TyS<'tcx> {
     /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
     /// [isize] => { [isize], isize }
     /// ```
-    pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
-        TypeWalker::new(self.into())
+    pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
+        TypeWalker::new(Some(tcx), self.into())
     }
 }
 
-// We push `GenericArg`s on the stack in reverse order so as to
-// maintain a pre-order traversal. As of the time of this
-// writing, the fact that the traversal is pre-order is not
-// known to be significant to any code, but it seems like the
-// natural order one would expect (basically, the order of the
-// types as they are written).
-fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) {
+/// We push `GenericArg`s on the stack in reverse order so as to
+/// maintain a pre-order traversal. As of the time of this
+/// writing, the fact that the traversal is pre-order is not
+/// known to be significant to any code, but it seems like the
+/// natural order one would expect (basically, the order of the
+/// types as they are written).
+fn push_inner<'tcx>(
+    expose_default_const_substs: Option<TyCtxt<'tcx>>,
+    stack: &mut TypeWalkerStack<'tcx>,
+    parent: GenericArg<'tcx>,
+) {
     match parent.unpack() {
         GenericArgKind::Type(parent_ty) => match *parent_ty.kind() {
             ty::Bool
@@ -196,7 +211,11 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
                 | ty::ConstKind::Error(_) => {}
 
                 ty::ConstKind::Unevaluated(ct) => {
-                    stack.extend(ct.substs.iter().rev());
+                    if let Some(tcx) = expose_default_const_substs {
+                        stack.extend(ct.substs(tcx).iter().rev());
+                    } else if let Some(substs) = ct.substs_ {
+                        stack.extend(substs.iter().rev());
+                    }
                 }
             }
         }
index d0284dd03023667ca43d58810bc7e93c961bcc94..ac30093ba826015fba0f9859172857b2f2d3861b 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op;
 use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
-use rustc_traits::type_op_prove_predicate_with_span;
+use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span};
 
 use std::fmt;
 use std::rc::Rc;
@@ -104,10 +104,11 @@ fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx
 impl<'tcx> ToUniverseInfo<'tcx>
     for Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>
 {
-    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        // Ascribe user type isn't usually called on types that have different
-        // bound regions.
-        UniverseInfo::other()
+    fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
+        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery {
+            canonical_query: self,
+            base_universe,
+        })))
     }
 }
 
@@ -267,6 +268,37 @@ fn nice_error(
     }
 }
 
+struct AscribeUserTypeQuery<'tcx> {
+    canonical_query: Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::AscribeUserType<'tcx>>>,
+    base_universe: ty::UniverseIndex,
+}
+
+impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
+    fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+        // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests,
+        // and is only the fallback when the nice error fails. Consider improving this some more.
+        tcx.sess.struct_span_err(span, "higher-ranked lifetime error")
+    }
+
+    fn base_universe(&self) -> ty::UniverseIndex {
+        self.base_universe
+    }
+
+    fn nice_error(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        span: Span,
+        placeholder_region: ty::Region<'tcx>,
+        error_region: Option<ty::Region<'tcx>>,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        tcx.infer_ctxt().enter_with_canonical(span, &self.canonical_query, |ref infcx, key, _| {
+            let mut fulfill_cx = <dyn TraitEngine<'_>>::new(tcx);
+            type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(span)).ok()?;
+            try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
+        })
+    }
+}
+
 fn try_extract_error_from_fulfill_cx<'tcx>(
     mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
     infcx: &InferCtxt<'_, 'tcx>,
index 7be3f5414879e742495797e33d0b3f8e70f239e4..4e079ed865ac31d4f29ecaea2285fd8d86407811 100644 (file)
@@ -5,11 +5,14 @@
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{
     hir::place::PlaceBase,
-    mir::{self, ClearCrossCrate, Local, LocalDecl, LocalInfo, LocalKind, Location},
+    mir::{
+        self, BindingForm, ClearCrossCrate, ImplicitSelfKind, Local, LocalDecl, LocalInfo,
+        LocalKind, Location,
+    },
 };
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, Symbol};
-use rustc_span::Span;
+use rustc_span::{BytePos, Span};
 
 use crate::borrow_check::diagnostics::BorrowedContentSource;
 use crate::borrow_check::MirBorrowckCtxt;
@@ -241,13 +244,74 @@ pub(crate) fn report_mutability_error(
                     .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
                     .unwrap_or(false) =>
             {
+                let decl = &self.body.local_decls[local];
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
-                err.span_suggestion(
-                    span,
-                    "try removing `&mut` here",
-                    String::new(),
-                    Applicability::MaybeIncorrect,
-                );
+                if let Some(mir::Statement {
+                    source_info,
+                    kind:
+                        mir::StatementKind::Assign(box (
+                            _,
+                            mir::Rvalue::Ref(
+                                _,
+                                mir::BorrowKind::Mut { allow_two_phase_borrow: false },
+                                _,
+                            ),
+                        )),
+                    ..
+                }) = &self.body[location.block].statements.get(location.statement_index)
+                {
+                    match decl.local_info {
+                        Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+                            mir::VarBindingForm {
+                                binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
+                                opt_ty_info: Some(sp),
+                                opt_match_place: _,
+                                pat_span: _,
+                            },
+                        )))) => {
+                            err.span_note(sp, "the binding is already a mutable borrow");
+                        }
+                        _ => {
+                            err.span_note(
+                                decl.source_info.span,
+                                "the binding is already a mutable borrow",
+                            );
+                        }
+                    }
+                    if let Ok(snippet) =
+                        self.infcx.tcx.sess.source_map().span_to_snippet(source_info.span)
+                    {
+                        if snippet.starts_with("&mut ") {
+                            // We don't have access to the HIR to get accurate spans, but we can
+                            // give a best effort structured suggestion.
+                            err.span_suggestion_verbose(
+                                source_info.span.with_hi(source_info.span.lo() + BytePos(5)),
+                                "try removing `&mut` here",
+                                String::new(),
+                                Applicability::MachineApplicable,
+                            );
+                        } else {
+                            // This can occur with things like `(&mut self).foo()`.
+                            err.span_help(source_info.span, "try removing `&mut` here");
+                        }
+                    } else {
+                        err.span_help(source_info.span, "try removing `&mut` here");
+                    }
+                } else if decl.mutability == Mutability::Not
+                    && !matches!(
+                        decl.local_info,
+                        Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
+                            ImplicitSelfKind::MutRef
+                        ))))
+                    )
+                {
+                    err.span_suggestion_verbose(
+                        decl.source_info.span.shrink_to_lo(),
+                        "consider making the binding mutable",
+                        "mut ".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
 
             // We want to suggest users use `let mut` for local (user
index e9ab62e1664f972778fa884a8b46a9f53f6f62cd..12fceeff0884c92a8f4f8ada963004d36b86c8f8 100644 (file)
@@ -82,15 +82,7 @@ pub(in crate::borrow_check) fn infer_opaque_types(
                             .find(|ur_vid| self.eval_equal(vid, **ur_vid))
                             .and_then(|ur_vid| self.definitions[*ur_vid].external_name)
                             .unwrap_or(infcx.tcx.lifetimes.re_root_empty),
-                        ty::ReLateBound(..) => region,
-                        ty::ReStatic => region,
-                        _ => {
-                            infcx.tcx.sess.delay_span_bug(
-                                span,
-                                &format!("unexpected concrete region in borrowck: {:?}", region),
-                            );
-                            region
-                        }
+                        _ => region,
                     });
 
                 debug!(?universal_concrete_type, ?universal_substs);
index f247d07e1f05e66bad3fbd20bcc1c209751583af..2864abde0022c15e2c54e60ce4d80e9bcfd66699 100644 (file)
@@ -160,7 +160,7 @@ impl<N: Idx> LivenessValues<N> {
     /// region. Returns whether any of them are newly added.
     crate fn add_elements(&mut self, row: N, locations: &HybridBitSet<PointIndex>) -> bool {
         debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
-        self.points.union_into_row(row, locations)
+        self.points.union_row(row, locations)
     }
 
     /// Adds all the control-flow points to the values for `r`.
@@ -294,7 +294,7 @@ impl<N: Idx> RegionValues<N> {
     /// the region `to` in `self`.
     crate fn merge_liveness<M: Idx>(&mut self, to: N, from: M, values: &LivenessValues<M>) {
         if let Some(set) = values.points.row(from) {
-            self.points.union_into_row(to, set);
+            self.points.union_row(to, set);
         }
     }
 
index 9fafcfafe67cdba8ba3b20619ffcfd1dd6361fc7..b501716a899752b41db2117da612e6ada703ff34 100644 (file)
@@ -1,6 +1,5 @@
 use std::fmt;
 
-use rustc_hir as hir;
 use rustc_infer::infer::canonical::Canonical;
 use rustc_infer::traits::query::NoSolution;
 use rustc_middle::mir::ConstraintCategory;
@@ -88,7 +87,7 @@ pub(super) fn prove_trait_ref(
         self.prove_predicates(
             Some(ty::PredicateKind::Trait(ty::TraitPredicate {
                 trait_ref,
-                constness: hir::Constness::NotConst,
+                constness: ty::BoundConstness::NotConst,
             })),
             locations,
             category,
index 012d67255d13bd6b96171cbb0a48104d6c41eb68..6426098d843fe80fd2dd709de1a3dcd3b7fc7fab 100644 (file)
@@ -256,6 +256,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
         let constraint_sets: Vec<_> = unnormalized_input_output_tys
             .flat_map(|ty| {
                 debug!("build: input_or_output={:?}", ty);
+                // We add implied bounds from both the unnormalized and normalized ty
+                // See issue #87748
+                let constraints_implied_1 = self.add_implied_bounds(ty);
                 let TypeOpOutput { output: ty, constraints: constraints1, .. } = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
@@ -271,9 +274,21 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                             canonicalized_query: None,
                         }
                     });
-                let constraints2 = self.add_implied_bounds(ty);
+                // Note: we need this in examples like
+                // ```
+                // trait Foo {
+                //   type Bar;
+                //   fn foo(&self) -> &Self::Bar;
+                // }
+                // impl Foo for () {
+                //   type Bar = ();
+                //   fn foo(&self) ->&() {}
+                // }
+                // ```
+                // Both &Self::Bar and &() are WF
+                let constraints_implied_2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
-                constraints1.into_iter().chain(constraints2)
+                constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
             })
             .collect();
 
index f8989a7d9df1c2be7e7c018fbdafe2e15651e1a8..ba9b6926526be010208f568415a9602c2043c62f 100644 (file)
@@ -9,7 +9,9 @@
 
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::*;
-use rustc_middle::ty::Ty;
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::{self, Ty};
+use rustc_trait_selection::traits::query::normalize::AtExt;
 
 use rustc_index::vec::Idx;
 use rustc_span::Span;
@@ -162,17 +164,49 @@ pub(super) fn equate_inputs_and_outputs(
     fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
         debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);
 
-        if let Err(terr) =
+        if let Err(_) =
             self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
         {
-            span_mirbug!(
-                self,
-                Location::START,
-                "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
-                a,
-                b,
-                terr
-            );
+            // FIXME(jackh726): This is a hack. It's somewhat like
+            // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
+            // like to normalize *before* inserting into `local_decls`, but
+            // doing so ends up causing some other trouble.
+            let b = match self
+                .infcx
+                .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                .normalize(b)
+            {
+                Ok(n) => {
+                    debug!("equate_inputs_and_outputs: {:?}", n);
+                    if n.obligations.iter().all(|o| {
+                        matches!(
+                            o.predicate.kind().skip_binder(),
+                            ty::PredicateKind::RegionOutlives(_)
+                                | ty::PredicateKind::TypeOutlives(_)
+                        )
+                    }) {
+                        n.value
+                    } else {
+                        b
+                    }
+                }
+                Err(_) => {
+                    debug!("equate_inputs_and_outputs: NoSolution");
+                    b
+                }
+            };
+            if let Err(terr) =
+                self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
+            {
+                span_mirbug!(
+                    self,
+                    Location::START,
+                    "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
+                    a,
+                    b,
+                    terr
+                );
+            }
         }
     }
 }
index e411f1dc10889d901884a04cd46a711087cdb118..566c11811e6e1108267411a5d79c688ed0809946 100644 (file)
@@ -171,7 +171,7 @@ fn add_extra_drop_facts(
         for (local, location) in drop_used {
             if !live_locals.contains(&local) {
                 let local_ty = self.cx.body.local_decls[local].ty;
-                if local_ty.has_free_regions() {
+                if local_ty.has_free_regions(self.cx.typeck.tcx()) {
                     self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
                 }
             }
index 35bb6ef6c2d6e1ee5678e18d0d3604f15f6130eb..639bcb8fa94efb7f3768665349a0508e5b703efe 100644 (file)
@@ -377,8 +377,8 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                 },
                 _ => None,
             };
-            if let Some(ty::Unevaluated { def, substs, promoted }) = maybe_uneval {
-                if let Some(promoted) = promoted {
+            if let Some(uv) = maybe_uneval {
+                if let Some(promoted) = uv.promoted {
                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
                                      promoted: &Body<'tcx>,
                                      ty,
@@ -413,8 +413,8 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
                         ConstraintCategory::Boring,
                         self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
                             constant.literal.ty(),
-                            def.did,
-                            UserSubsts { substs, user_self_ty: None },
+                            uv.def.did,
+                            UserSubsts { substs: uv.substs(self.tcx()), user_self_ty: None },
                         )),
                     ) {
                         span_mirbug!(
@@ -1053,6 +1053,7 @@ fn check_user_type_annotations(&mut self) {
         );
         for user_annotation in self.user_type_annotations {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
+            let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
             let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
             match annotation {
                 UserType::Ty(mut ty) => {
index dc6a6b0b9f3d8bca119dcd52d4dde902e5ac5a29..3e8a93e08c29d9c6739735e0f70d023f10f2efb9 100644 (file)
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::traits::Reveal;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, subst::Subst, TyCtxt};
 use rustc_span::source_map::Span;
-use rustc_target::abi::{Abi, LayoutOf};
+use rustc_target::abi::Abi;
 use std::borrow::Cow;
 use std::convert::TryInto;
 
index 697e98311e2d37fa6d227bb1a018f52dbd521389..4c4b0bd2d1f271c215d8e6b9591e9f3ee077e851 100644 (file)
@@ -5,9 +5,9 @@
 use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
 use rustc_middle::mir::CastKind;
 use rustc_middle::ty::adjustment::PointerCast;
-use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
+use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, FloatTy, Ty, TypeAndMut};
-use rustc_target::abi::{Integer, LayoutOf, Variants};
+use rustc_target::abi::{Integer, Variants};
 
 use super::{
     util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
@@ -340,7 +340,7 @@ fn unsize_into(
                 // Example: `Arc<T>` -> `Arc<Trait>`
                 // here we need to increase the size of every &T thin ptr field to a fat ptr
                 for i in 0..src.layout.fields.count() {
-                    let cast_ty_field = cast_ty.field(self, i)?;
+                    let cast_ty_field = cast_ty.field(self, i);
                     if cast_ty_field.is_zst() {
                         continue;
                     }
index 516ef4f4e53ca8130a1c9a5d9f73b57d4c5f7982..05502d8b21f1ce7a5026d4d74927c1b4db41c495 100644 (file)
@@ -8,18 +8,18 @@
 use rustc_macros::HashStable;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::{self, TyAndLayout};
+use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_session::Limit;
 use rustc_span::{Pos, Span};
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
-    AllocId, GlobalId, Immediate, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory,
-    MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar, ScalarMaybeUninit,
-    StackPopJump,
+    AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace,
+    MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance, Scalar,
+    ScalarMaybeUninit, StackPopJump,
 };
 use crate::transform::validate::equal_up_to_regions;
 use crate::util::storage::AlwaysLiveLocals;
@@ -272,11 +272,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 write!(f, "inside `{}`", self.instance)?;
             }
             if !self.span.is_dummy() {
-                let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo());
+                let sm = tcx.sess.source_map();
+                let lo = sm.lookup_char_pos(self.span.lo());
                 write!(
                     f,
                     " at {}:{}:{}",
-                    lo.file.name.prefer_local(),
+                    sm.filename_for_diagnostics(&lo.file.name),
                     lo.line,
                     lo.col.to_usize() + 1
                 )?;
@@ -312,15 +313,22 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
     }
 }
 
-impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> {
+    type LayoutOfResult = InterpResult<'tcx, TyAndLayout<'tcx>>;
 
     #[inline]
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx
-            .layout_of(self.param_env.and(ty))
-            .map_err(|layout| err_inval!(Layout(layout)).into())
+    fn layout_tcx_at_span(&self) -> Span {
+        self.tcx.span
+    }
+
+    #[inline]
+    fn handle_layout_err(
+        &self,
+        err: LayoutError<'tcx>,
+        _: Span,
+        _: Ty<'tcx>,
+    ) -> InterpErrorInfo<'tcx> {
+        err_inval!(Layout(err)).into()
     }
 }
 
@@ -592,7 +600,7 @@ pub(super) fn size_and_align_of(
                 // Recurse to get the size of the dynamically sized field (must be
                 // the last field).  Can't have foreign types here, how would we
                 // adjust alignment and size for them?
-                let field = layout.field(self, layout.fields.count() - 1)?;
+                let field = layout.field(self, layout.fields.count() - 1);
                 let (unsized_size, unsized_align) =
                     match self.size_and_align_of(metadata, &field)? {
                         Some(size_and_align) => size_and_align,
@@ -645,7 +653,7 @@ pub(super) fn size_and_align_of(
 
             ty::Slice(_) | ty::Str => {
                 let len = metadata.unwrap_meta().to_machine_usize(self)?;
-                let elem = layout.field(self, 0)?;
+                let elem = layout.field(self, 0);
 
                 // Make sure the slice is not too big.
                 let size = elem.size.checked_mul(len, self).ok_or_else(|| {
index bfab886b6ee4f9fd2ab9c40b62099c287170884f..07e974b72664bbefc7103a91f80532ea3135ec6e 100644 (file)
     BinOp,
 };
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, Align, LayoutOf as _, Primitive, Size};
+use rustc_target::abi::{Abi, Align, Primitive, Size};
 
 use super::{
     util::ensure_monomorphic_enough, CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy,
index 022129b2a22046a04806c4dbb893cbd4555aa5a1..d4cbba18029311bff2079acb73220ddb4d42bf62 100644 (file)
@@ -3,9 +3,9 @@
 use rustc_ast::Mutability;
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::mir::TerminatorKind;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::subst::Subst;
 use rustc_span::{Span, Symbol};
-use rustc_target::abi::LayoutOf;
 
 use crate::interpret::{
     intrinsics::{InterpCx, Machine},
index 81f78621d1458520d90aa98b906da2125f77776d..e67a6690836ad2a9ed8f12599369a07099775d3c 100644 (file)
@@ -7,11 +7,11 @@
 use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
-use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
 use rustc_middle::ty::{ConstInt, Ty};
 use rustc_middle::{mir, ty};
-use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding};
+use rustc_target::abi::{Abi, HasDataLayout, Size, TagEncoding};
 use rustc_target::abi::{VariantIdx, Variants};
 
 use super::{
@@ -364,7 +364,7 @@ pub fn operand_field(
             Err(value) => value,
         };
 
-        let field_layout = op.layout.field(self, field)?;
+        let field_layout = op.layout.field(self, field);
         if field_layout.is_zst() {
             let immediate = Scalar::ZST.into();
             return Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout });
@@ -555,9 +555,9 @@ pub(super) fn eval_operands(
         match val.val {
             ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
             ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                let instance = self.resolve(def, substs)?;
-                Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into())
+            ty::ConstKind::Unevaluated(uv) => {
+                let instance = self.resolve(uv.def, uv.substs(*self.tcx))?;
+                Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
             }
             ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
                 span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val)
index 79b493d74e19b47006653f8bbd6fb0ccad7012e0..ac000b1bb566fe7ea9c037167da15e730073085e 100644 (file)
@@ -3,8 +3,8 @@
 use rustc_apfloat::Float;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
-use rustc_middle::ty::{self, layout::TyAndLayout, FloatTy, Ty};
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
+use rustc_middle::ty::{self, FloatTy, Ty};
 
 use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
 
index 91fcc3495b1c12abeaa3523d705462214f3db23d..95a44e3fecf3d19b249c1f81924f123b5ebc010b 100644 (file)
@@ -8,10 +8,10 @@
 use rustc_ast::Mutability;
 use rustc_macros::HashStable;
 use rustc_middle::mir;
-use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding};
-use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants};
+use rustc_target::abi::{HasDataLayout, Size, VariantIdx, Variants};
 
 use super::{
     alloc_range, mir_assign_valid_types, AllocId, AllocRef, AllocRefMut, CheckInAllocMsg,
@@ -355,7 +355,7 @@ pub fn mplace_field(
         field: usize,
     ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let offset = base.layout.fields.offset(field);
-        let field_layout = base.layout.field(self, field)?;
+        let field_layout = base.layout.field(self, field);
 
         // Offset may need adjustment for unsized fields.
         let (meta, offset) = if field_layout.is_unsized() {
@@ -405,7 +405,7 @@ pub fn mplace_index(
                 }
                 let offset = stride * index; // `Size` multiplication
                 // All fields have the same layout.
-                let field_layout = base.layout.field(self, 0)?;
+                let field_layout = base.layout.field(self, 0);
 
                 assert!(!field_layout.is_unsized());
                 base.offset(offset, MemPlaceMeta::None, field_layout, self)
@@ -430,7 +430,7 @@ pub(super) fn mplace_array_fields(
             FieldsShape::Array { stride, .. } => stride,
             _ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
         };
-        let layout = base.layout.field(self, 0)?;
+        let layout = base.layout.field(self, 0);
         let dl = &self.tcx.data_layout;
         // `Size` multiplication
         Ok((0..len).map(move |i| base.offset(stride * i, MemPlaceMeta::None, layout, dl)))
index f2a8a067dfac2a11287515d4a2e927aec3c62946..1e96581c392d25e31d1d688494f0a865eddc8c1a 100644 (file)
@@ -4,7 +4,7 @@
 
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::LayoutOf;
 
 use super::{InterpCx, Machine};
 
index d87aa4a6267ecae614978192e9c770eb0b673650..1c8e5e9e23c3caefab88cd27f834bd67c5b8db48 100644 (file)
@@ -2,13 +2,13 @@
 use std::convert::TryFrom;
 
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::ty::layout::{self, TyAndLayout};
+use rustc_middle::ty::layout::{self, LayoutOf as _, TyAndLayout};
 use rustc_middle::ty::Instance;
 use rustc_middle::{
     mir,
     ty::{self, Ty},
 };
-use rustc_target::abi::{self, LayoutOf as _};
+use rustc_target::abi;
 use rustc_target::spec::abi::Abi;
 
 use super::{
@@ -461,7 +461,7 @@ fn eval_fn_call(
                 // a thin pointer.
                 assert!(receiver_place.layout.is_unsized());
                 let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
-                let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
+                let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0);
                 // Adjust receiver argument.
                 args[0] = OpTy::from(ImmTy::from_immediate(
                     Scalar::from_maybe_pointer(receiver_place.ptr, self).into(),
index 89f34cd07aa4b15c33ee5e871ed1dc9af7c2ebc7..eb0fdebb665faa2bea8e83168f0700b8ce916d2d 100644 (file)
@@ -9,7 +9,7 @@
     T: TypeFoldable<'tcx>,
 {
     debug!("ensure_monomorphic_enough: ty={:?}", ty);
-    if !ty.needs_subst() {
+    if !ty.potentially_needs_subst() {
         return Ok(());
     }
 
@@ -21,19 +21,12 @@ struct UsedParamsNeedSubstVisitor<'tcx> {
     impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
         type BreakTy = FoundParam;
 
-        fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if !c.needs_subst() {
-                return ControlFlow::CONTINUE;
-            }
-
-            match c.val {
-                ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
-                _ => c.super_visit_with(self),
-            }
+        fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+            Some(self.tcx)
         }
 
         fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if !ty.needs_subst() {
+            if !ty.potentially_needs_subst() {
                 return ControlFlow::CONTINUE;
             }
 
@@ -50,7 +43,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         let is_used = unused_params.contains(index).map_or(true, |unused| !unused);
                         // Only recurse when generic parameters in fns, closures and generators
                         // are used and require substitution.
-                        match (is_used, subst.needs_subst()) {
+                        match (is_used, subst.definitely_needs_subst(self.tcx)) {
                             // Just in case there are closures or generators within this subst,
                             // recurse.
                             (true, true) => return subst.super_visit_with(self),
@@ -73,6 +66,13 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 _ => ty.super_visit_with(self),
             }
         }
+
+        fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+            match c.val {
+                ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
+                _ => c.super_visit_with(self),
+            }
+        }
     }
 
     let mut vis = UsedParamsNeedSubstVisitor { tcx };
index b0cd6405eb9014f2c8cfc3bc085a8be13cd64db2..03e0a8e7901d94c86f2077dd026e207e1aaea148 100644 (file)
@@ -7,15 +7,14 @@
 use std::convert::TryFrom;
 use std::fmt::Write;
 use std::num::NonZeroUsize;
-use std::ops::RangeInclusive;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_middle::mir::interpret::InterpError;
 use rustc_middle::ty;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_target::abi::{Abi, LayoutOf, Scalar as ScalarAbi, Size, VariantIdx, Variants};
+use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
 
 use std::hash::Hash;
 
@@ -181,22 +180,10 @@ fn write_path(out: &mut String, path: &[PathElem]) {
     }
 }
 
-// Test if a range that wraps at overflow contains `test`
-fn wrapping_range_contains(r: &RangeInclusive<u128>, test: u128) -> bool {
-    let (lo, hi) = r.clone().into_inner();
-    if lo > hi {
-        // Wrapped
-        (..=hi).contains(&test) || (lo..).contains(&test)
-    } else {
-        // Normal
-        r.contains(&test)
-    }
-}
-
 // Formats such that a sentence like "expected something {}" to mean
 // "expected something <in the given range>" makes sense.
-fn wrapping_range_format(r: &RangeInclusive<u128>, max_hi: u128) -> String {
-    let (lo, hi) = r.clone().into_inner();
+fn wrapping_range_format(r: WrappingRange, max_hi: u128) -> String {
+    let WrappingRange { start: lo, end: hi } = r;
     assert!(hi <= max_hi);
     if lo > hi {
         format!("less or equal to {}, or greater or equal to {}", hi, lo)
@@ -634,8 +621,8 @@ fn visit_scalar(
         scalar_layout: &ScalarAbi,
     ) -> InterpResult<'tcx> {
         let value = self.read_scalar(op)?;
-        let valid_range = &scalar_layout.valid_range;
-        let (lo, hi) = valid_range.clone().into_inner();
+        let valid_range = scalar_layout.valid_range.clone();
+        let WrappingRange { start: lo, end: hi } = valid_range;
         // Determine the allowed range
         // `max_hi` is as big as the size fits
         let max_hi = u128::MAX >> (128 - op.layout.size.bits());
@@ -684,7 +671,7 @@ fn visit_scalar(
             Ok(int) => int.assert_bits(op.layout.size),
         };
         // Now compare. This is slightly subtle because this is a special "wrap-around" range.
-        if wrapping_range_contains(&valid_range, bits) {
+        if valid_range.contains(bits) {
             Ok(())
         } else {
             throw_validation_failure!(self.path,
index 95c4237f38396b58c9e5c12c9f8eba2b40f67b56..4cb362238c1c5106b6aa5029ec7d88188d9b00d3 100644 (file)
@@ -573,7 +573,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     let type_length = instance
         .substs
         .iter()
-        .flat_map(|arg| arg.walk())
+        .flat_map(|arg| arg.walk(tcx))
         .filter(|arg| match arg.unpack() {
             GenericArgKind::Type(_) | GenericArgKind::Const(_) => true,
             GenericArgKind::Lifetime(_) => false,
@@ -1149,6 +1149,7 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
         match item.kind {
             hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::Use(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::TyAlias(..)
             | hir::ItemKind::Trait(..)
index fea1adfa3d58b784399f667affc59c533856aa81..3c55a4b0a8fb1e52040d7a3e6055c2aeb47921d9 100644 (file)
@@ -178,7 +178,7 @@ fn mark_used_by_predicates<'tcx>(
             // Consider all generic params in a predicate as used if any other parameter in the
             // predicate is used.
             let any_param_used = {
-                let mut vis = HasUsedGenericParams { unused_parameters };
+                let mut vis = HasUsedGenericParams { tcx, unused_parameters };
                 predicate.visit_with(&mut vis).is_break()
             };
 
@@ -283,9 +283,12 @@ fn visit_ty(&mut self, ty: Ty<'tcx>, _: TyContext) {
 }
 
 impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
     #[instrument(skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -295,7 +298,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 self.unused_parameters.clear(param.index);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
+            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted: Some(p)})
                 // Avoid considering `T` unused when constants are of the form:
                 //   `<Self as Foo<T>>::foo::promoted[p]`
                 if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
@@ -306,10 +309,10 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 self.visit_body(&promoted[p]);
                 ControlFlow::CONTINUE
             }
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None })
-                if self.tcx.def_kind(def.did) == DefKind::AnonConst =>
+            ty::ConstKind::Unevaluated(uv)
+                if self.tcx.def_kind(uv.def.did) == DefKind::AnonConst =>
             {
-                self.visit_child_body(def.did, substs);
+                self.visit_child_body(uv.def.did, uv.substs(self.tcx));
                 ControlFlow::CONTINUE
             }
             _ => c.super_visit_with(self),
@@ -318,7 +321,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
 
     #[instrument(skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -346,16 +349,21 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
 }
 
 /// Visitor used to check if a generic parameter is used.
-struct HasUsedGenericParams<'a> {
+struct HasUsedGenericParams<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
     unused_parameters: &'a FiniteBitSet<u32>,
 }
 
-impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
+impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
     type BreakTy = ();
 
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     #[instrument(skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !c.has_param_types_or_consts() {
+        if !c.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
@@ -373,7 +381,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
 
     #[instrument(skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if !ty.has_param_types_or_consts() {
+        if !ty.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
         }
 
index 8c3d828894c8ef4f105d35474a4d49991e46dbaf..8083ec954478a136cb6dd25599b6a4b208a21ebb 100644 (file)
@@ -163,7 +163,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 
     let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
     let mut body =
-        new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
+        new_body(tcx, source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
 
     if ty.is_some() {
         // The first argument (index 0), but add 1 for the return value.
@@ -202,6 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
 }
 
 fn new_body<'tcx>(
+    tcx: TyCtxt<'tcx>,
     source: MirSource<'tcx>,
     basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
@@ -209,6 +210,7 @@ fn new_body<'tcx>(
     span: Span,
 ) -> Body<'tcx> {
     Body::new(
+        tcx,
         source,
         basic_blocks,
         IndexVec::from_elem_n(
@@ -353,7 +355,14 @@ fn into_mir(self) -> Body<'tcx> {
             self.def_id,
             self.sig.inputs_and_output[0],
         ));
-        new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
+        new_body(
+            self.tcx,
+            source,
+            self.blocks,
+            self.local_decls,
+            self.sig.inputs().len(),
+            self.span,
+        )
     }
 
     fn source_info(&self) -> SourceInfo {
@@ -851,8 +860,14 @@ fn build_call_shim<'tcx>(
         block(&mut blocks, vec![], TerminatorKind::Resume, true);
     }
 
-    let mut body =
-        new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
+    let mut body = new_body(
+        tcx,
+        MirSource::from_instance(instance),
+        blocks,
+        local_decls,
+        sig.inputs().len(),
+        span,
+    );
 
     if let Abi::RustCall = sig.abi {
         body.spread_arg = Some(Local::new(sig.inputs().len()));
@@ -917,6 +932,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
 
     let source = MirSource::item(ctor_id);
     let body = new_body(
+        tcx,
         source,
         IndexVec::from_elem_n(start_block, 1),
         local_decls,
index 09e908e675731e5be10295be1dc02e1e36073e0c..0c381276823598493e8aa12acd9fa6f30542271f 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
 use rustc_span::{sym, Span, Symbol};
@@ -365,7 +365,7 @@ fn check_static(&mut self, def_id: DefId, span: Span) {
     fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
         let kind = self.body.local_kind(local);
 
-        for ty in ty.walk() {
+        for ty in ty.walk(self.tcx) {
             let ty = match ty.unpack() {
                 GenericArgKind::Type(ty) => ty,
 
@@ -793,7 +793,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
 
                 let fn_ty = func.ty(body, tcx);
 
-                let (mut callee, substs) = match *fn_ty.kind() {
+                let (mut callee, mut substs) = match *fn_ty.kind() {
                     ty::FnDef(def_id, substs) => (def_id, substs),
 
                     ty::FnPtr(_) => {
@@ -805,6 +805,8 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                     }
                 };
 
+                let mut nonconst_call_permission = false;
+
                 // Attempting to call a trait method?
                 if let Some(trait_id) = tcx.trait_of_item(callee) {
                     trace!("attempting to call a trait method");
@@ -819,23 +821,56 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                         param_env,
                         Binder::dummy(TraitPredicate {
                             trait_ref,
-                            constness: hir::Constness::Const,
+                            constness: ty::BoundConstness::ConstIfConst,
                         }),
                     );
 
                     let implsrc = tcx.infer_ctxt().enter(|infcx| {
-                        let mut selcx = SelectionContext::new(&infcx);
-                        selcx.select(&obligation).unwrap()
+                        let mut selcx =
+                            SelectionContext::with_constness(&infcx, hir::Constness::Const);
+                        selcx.select(&obligation)
                     });
 
-                    // If the method is provided via a where-clause that does not use the `?const`
-                    // opt-out, the call is allowed.
-                    if let Some(ImplSource::Param(_, hir::Constness::Const)) = implsrc {
-                        debug!(
-                            "const_trait_impl: provided {:?} via where-clause in {:?}",
-                            trait_ref, param_env
-                        );
-                        return;
+                    match implsrc {
+                        Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
+                            debug!(
+                                "const_trait_impl: provided {:?} via where-clause in {:?}",
+                                trait_ref, param_env
+                            );
+                            return;
+                        }
+                        Ok(Some(ImplSource::UserDefined(data))) => {
+                            let callee_name = tcx.item_name(callee);
+                            if let Some(&did) = tcx
+                                .associated_item_def_ids(data.impl_def_id)
+                                .iter()
+                                .find(|did| tcx.item_name(**did) == callee_name)
+                            {
+                                // using internal substs is ok here, since this is only
+                                // used for the `resolve` call below
+                                substs = InternalSubsts::identity_for_item(tcx, did);
+                                callee = did;
+                            }
+                        }
+                        _ if !tcx.is_const_fn_raw(callee) => {
+                            // At this point, it is only legal when the caller is marked with
+                            // #[default_method_body_is_const], and the callee is in the same
+                            // trait.
+                            let callee_trait = tcx.trait_of_item(callee);
+                            if callee_trait.is_some() {
+                                if tcx.has_attr(caller, sym::default_method_body_is_const) {
+                                    if tcx.trait_of_item(caller) == callee_trait {
+                                        nonconst_call_permission = true;
+                                    }
+                                }
+                            }
+
+                            if !nonconst_call_permission {
+                                self.check_op(ops::FnCallNonConst);
+                                return;
+                            }
+                        }
+                        _ => {}
                     }
 
                     // Resolve a trait method call to its concrete implementation, which may be in a
@@ -875,34 +910,16 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 let is_intrinsic = tcx.fn_sig(callee).abi() == RustIntrinsic;
 
                 if !tcx.is_const_fn_raw(callee) {
-                    let mut permitted = false;
-
-                    let callee_trait = tcx.trait_of_item(callee);
-                    if let Some(trait_id) = callee_trait {
-                        if tcx.has_attr(caller, sym::default_method_body_is_const) {
-                            // permit call to non-const fn when caller has default_method_body_is_const..
-                            if tcx.trait_of_item(caller) == callee_trait {
-                                // ..and caller and callee are in the same trait.
-                                permitted = true;
-                            }
-                        }
-                        if !permitted {
-                            // if trait's impls are all const, permit the call.
-                            let mut const_impls = true;
-                            tcx.for_each_relevant_impl(trait_id, substs.type_at(0), |imp| {
-                                if const_impls {
-                                    if let hir::Constness::NotConst = tcx.impl_constness(imp) {
-                                        const_impls = false;
-                                    }
-                                }
-                            });
-                            if const_impls {
-                                permitted = true;
-                            }
+                    if tcx.trait_of_item(callee).is_some() {
+                        if tcx.has_attr(callee, sym::default_method_body_is_const) {
+                            // To get to here we must have already found a const impl for the
+                            // trait, but for it to still be non-const can be that the impl is
+                            // using default method bodies.
+                            nonconst_call_permission = true;
                         }
                     }
 
-                    if !permitted {
+                    if !nonconst_call_permission {
                         self.check_op(ops::FnCallNonConst);
                         return;
                     }
index ac8c748ea85710a4dc9d09d01ac75f75ae499472..413a9638eb37b172717d4473f48079215170cf72 100644 (file)
@@ -247,7 +247,7 @@ pub fn in_operand<Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Oper
 
     // Check the qualifs of the value of `const` items.
     if let Some(ct) = constant.literal.const_for_ty() {
-        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val {
+        if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val {
             assert!(promoted.is_none());
             // Don't peek inside trait associated constants.
             if cx.tcx.trait_of_item(def.did).is_none() {
index 4578f04c0345260a053bae3edef5a20f2de929a0..71c07be4c6d8de860919f58a7e51f38cc4d19e95 100644 (file)
     Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
     StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
 };
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{
     self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_session::lint;
 use rustc_span::{def_id::DefId, Span};
-use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 
@@ -120,7 +120,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             .predicates_of(def_id.to_def_id())
             .predicates
             .iter()
-            .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
+            .filter_map(|(p, _)| if p.is_global(tcx) { Some(*p) } else { None });
         if traits::impossible_predicates(
             tcx,
             traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
@@ -132,6 +132,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("ConstProp starting for {:?}", def_id);
 
         let dummy_body = &Body::new(
+            tcx,
             body.source,
             body.basic_blocks().clone(),
             body.source_scopes.clone(),
@@ -329,12 +330,12 @@ struct ConstPropagator<'mir, 'tcx> {
     source_info: Option<SourceInfo>,
 }
 
-impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
+impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> {
+    type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty))
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span, _: Ty<'tcx>) -> LayoutError<'tcx> {
+        err
     }
 }
 
@@ -345,13 +346,20 @@ fn data_layout(&self) -> &TargetDataLayout {
     }
 }
 
-impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
+impl<'mir, 'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 }
 
+impl<'mir, 'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'mir, 'tcx> {
+    #[inline]
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        self.param_env
+    }
+}
+
 impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     fn new(
         body: &Body<'tcx>,
@@ -468,7 +476,7 @@ fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
     /// Returns the value, if any, of evaluating `c`.
     fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         // FIXME we need to revisit this for #67176
-        if c.needs_subst() {
+        if c.definitely_needs_subst(self.tcx) {
             return None;
         }
 
@@ -483,14 +491,14 @@ fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Opti
                             // Promoteds must lint and not error as the user didn't ask for them
                             ConstKind::Unevaluated(ty::Unevaluated {
                                 def: _,
-                                substs: _,
+                                substs_: _,
                                 promoted: Some(_),
                             }) => true,
                             // Out of backwards compatibility we cannot report hard errors in unused
                             // generic functions using associated constants of the generic parameters.
-                            _ => c.literal.needs_subst(),
+                            _ => c.literal.definitely_needs_subst(*tcx),
                         },
-                        ConstantKind::Val(_, ty) => ty.needs_subst(),
+                        ConstantKind::Val(_, ty) => ty.definitely_needs_subst(*tcx),
                     };
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
@@ -720,7 +728,7 @@ fn const_prop(
         }
 
         // FIXME we need to revisit this for #67176
-        if rvalue.needs_subst() {
+        if rvalue.definitely_needs_subst(self.tcx) {
             return None;
         }
 
index 26fe796cb916ffdce81e967fd6c27d1c36a88872..ba2c91a9347ec5dd45ffc0a33250f8248d86b997 100644 (file)
@@ -49,7 +49,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                     // Handle calls to `transmute`
                     if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
                         let arg_ty = args[0].ty(self.body, self.tcx);
-                        for generic_inner_ty in arg_ty.walk() {
+                        for generic_inner_ty in arg_ty.walk(self.tcx) {
                             if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
                                 if let Some((fn_id, fn_substs)) =
                                     FunctionItemRefChecker::is_fn_ref(inner_ty)
@@ -110,7 +110,7 @@ fn check_bound_args(
                 let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs();
                 for (arg_num, arg_def) in arg_defs.iter().enumerate() {
                     // For all types reachable from the argument type in the fn sig
-                    for generic_inner_ty in arg_def.walk() {
+                    for generic_inner_ty in arg_def.walk(self.tcx) {
                         if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
                             // If the inner type matches the type bound by `Pointer`
                             if TyS::same_type(inner_ty, bound_ty) {
index 963f93a1acec1d32fd4bc9eace81795dba5f1005..acdaa5b456857becc07abb70e482f0440a711b32 100644 (file)
@@ -626,7 +626,7 @@ fn compute_storage_conflicts(
     // Locals that are always live or ones that need to be stored across
     // suspension points are not eligible for overlap.
     let mut ineligible_locals = always_live_locals.into_inner();
-    ineligible_locals.intersect(saved_locals);
+    ineligible_locals.intersect(&**saved_locals);
 
     // Compute the storage conflicts for all eligible locals.
     let mut visitor = StorageConflictVisitor {
@@ -701,7 +701,7 @@ fn apply_state(&mut self, flow_state: &BitSet<Local>, loc: Location) {
         }
 
         let mut eligible_storage_live = flow_state.clone();
-        eligible_storage_live.intersect(&self.saved_locals);
+        eligible_storage_live.intersect(&**self.saved_locals);
 
         for local in eligible_storage_live.iter() {
             self.local_conflicts.union_row_with(&eligible_storage_live, local);
index c333667b3ad135490357a6fc74e15925409dc072..8e9da31eba11f04bcff01ea0c3348ce8e48d0ef1 100644 (file)
@@ -607,13 +607,7 @@ fn dest_needs_borrow(place: Place<'_>) -> bool {
                 }
 
                 // Insert all of the (mapped) parts of the callee body into the caller.
-                caller_body.local_decls.extend(
-                    // FIXME(eddyb) make `Range<Local>` iterable so that we can use
-                    // `callee_body.local_decls.drain(callee_body.vars_and_temps())`
-                    callee_body
-                        .vars_and_temps_iter()
-                        .map(|local| callee_body.local_decls[local].clone()),
-                );
+                caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
                 caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..));
                 caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
                 caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));
index c9eafafff57cd2f6f76f758dfa2d34faa483acf3..385394ba67d4d2e8fa0fdc2f8747c59129817d11 100644 (file)
@@ -89,7 +89,7 @@ fn process(
                     // FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
                     // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
                     // needs some more analysis.
-                    if callee.needs_subst() {
+                    if callee.definitely_needs_subst(tcx) {
                         continue;
                     }
                 }
index fa648a6dd49ff5f2d2c22d33f9ed26b137a86d16..d4c2456e9a4367f9591b7db075163c7f845da290 100644 (file)
@@ -400,7 +400,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
         }
     }
 
-    debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
+    debug_assert!(!body.has_free_regions(tcx), "Free regions in MIR for CTFE");
 
     body
 }
@@ -594,7 +594,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
     run_optimization_passes(tcx, &mut body);
 
-    debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
+    debug_assert!(!body.has_free_regions(tcx), "Free regions in optimized MIR");
 
     body
 }
@@ -621,7 +621,7 @@ fn promoted_mir<'tcx>(
         run_post_borrowck_cleanup_passes(tcx, body);
     }
 
-    debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
+    debug_assert!(!promoted.has_free_regions(tcx), "Free regions in promoted MIR");
 
     tcx.arena.alloc(promoted)
 }
index 822b422985cb3e009f9016f2cd619e11dc71849e..1b43670ba3ac103eaa3021f0b2e2a0c7c69545c7 100644 (file)
@@ -859,13 +859,17 @@ fn promote_candidate(
                             ty,
                             val: ty::ConstKind::Unevaluated(ty::Unevaluated {
                                 def,
-                                substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
-                                    if let ty::GenericParamDefKind::Lifetime = param.kind {
-                                        tcx.lifetimes.re_erased.into()
-                                    } else {
-                                        tcx.mk_param_from_def(param)
-                                    }
-                                }),
+                                substs_: Some(InternalSubsts::for_item(
+                                    tcx,
+                                    def.did,
+                                    |param, _| {
+                                        if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                            tcx.lifetimes.re_erased.into()
+                                        } else {
+                                            tcx.mk_param_from_def(param)
+                                        }
+                                    },
+                                )),
                                 promoted: Some(promoted_id),
                             }),
                         })
@@ -988,6 +992,7 @@ pub fn promote_candidates<'tcx>(
         scope.parent_scope = None;
 
         let promoted = Body::new(
+            tcx,
             body.source, // `promoted` gets filled in below
             IndexVec::new(),
             IndexVec::from_elem_n(scope, 1),
index 5d4ca871faa2e46d3e0d189649afee1fdf465fb1..73adc60577bfcf41e43f243ba057f77256c8d112 100644 (file)
@@ -24,7 +24,7 @@ pub fn is_disaligned<'tcx, L>(
     };
 
     let ty = place.ty(local_decls, tcx).ty;
-    match tcx.layout_raw(param_env.and(ty)) {
+    match tcx.layout_of(param_env.and(ty)) {
         Ok(layout) if layout.align.abi <= pack => {
             // If the packed alignment is greater or equal to the field alignment, the type won't be
             // further disaligned.
index 7598a011bb6771619541fbab1865cdcd1b2f23da..92591db668ce9b7a6f0e9b74ec0b8b48133f648c 100644 (file)
@@ -475,7 +475,7 @@ fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
                 ty::ConstKind::Unevaluated(uv) => format!(
                     "Unevaluated({}, {:?}, {:?})",
                     self.tcx.def_path_str(uv.def.did),
-                    uv.substs,
+                    uv.substs(self.tcx),
                     uv.promoted
                 ),
                 ty::ConstKind::Value(val) => format!("Value({:?})", val),
@@ -682,6 +682,12 @@ fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> +
     }
     struct CollectAllocIds(BTreeSet<AllocId>);
     impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
+        fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+            // `AllocId`s are only inside of `ConstKind::Value` which
+            // can't be part of the anon const default substs.
+            None
+        }
+
         fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             if let ty::ConstKind::Value(val) = c.val {
                 self.0.extend(alloc_ids_from_const(val));
index 21c5a64f82337f0482c02c47ee60fca11f870d95..22c44beb350ae9234339ea51c2b60c74f4836564 100644 (file)
@@ -52,11 +52,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             ExprKind::Match { scrutinee, ref arms } => {
                 this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms)
             }
-            ExprKind::If { cond, then, else_opt } => {
-                let local_scope = this.local_scope();
-                let (mut then_blk, mut else_blk) =
-                    this.then_else_blocks(block, &this.thir[cond], local_scope, source_info);
-                unpack!(then_blk = this.expr_into_dest(destination, then_blk, &this.thir[then]));
+            ExprKind::If { cond, then, else_opt, if_then_scope } => {
+                let then_blk;
+                let then_expr = &this.thir[then];
+                let then_source_info = this.source_info(then_expr.span);
+                let condition_scope = this.local_scope();
+
+                let mut else_blk = unpack!(
+                    then_blk = this.in_scope(
+                        (if_then_scope, then_source_info),
+                        LintLevel::Inherited,
+                        |this| {
+                            let (then_block, else_block) =
+                                this.in_if_then_scope(condition_scope, |this| {
+                                    let then_blk = unpack!(this.then_else_break(
+                                        block,
+                                        &this.thir[cond],
+                                        condition_scope,
+                                        condition_scope,
+                                        then_expr.span,
+                                    ));
+                                    this.expr_into_dest(destination, then_blk, then_expr)
+                                });
+                            then_block.and(else_block)
+                        },
+                    )
+                );
+
                 else_blk = if let Some(else_opt) = else_opt {
                     unpack!(this.expr_into_dest(destination, else_blk, &this.thir[else_opt]))
                 } else {
@@ -81,9 +103,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 join_block.unit()
             }
-            ExprKind::Let { ref pat, expr } => {
-                let (true_block, false_block) =
-                    this.lower_let(block, &this.thir[expr], pat, expr_span);
+            ExprKind::Let { expr, ref pat } => {
+                let scope = this.local_scope();
+                let (true_block, false_block) = this.in_if_then_scope(scope, |this| {
+                    this.lower_let_expr(block, &this.thir[expr], pat, scope, expr_span)
+                });
 
                 let join_block = this.cfg.start_new_block();
 
index a36af024ad8d0e92f52c84f8234ee3ebe09f6b51..ec54a2a0ec4eeefebd99d1ecad3dfe6268f28865 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_middle::thir::{self, *};
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
 use rustc_span::symbol::Symbol;
-use rustc_span::Span;
+use rustc_span::{BytePos, Pos, Span};
 use rustc_target::abi::VariantIdx;
 use smallvec::{smallvec, SmallVec};
 
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub(crate) fn then_else_blocks(
+    pub(crate) fn then_else_break(
         &mut self,
         mut block: BasicBlock,
         expr: &Expr<'tcx>,
-        scope: region::Scope,
-        source_info: SourceInfo,
-    ) -> (BasicBlock, BasicBlock) {
+        temp_scope: region::Scope,
+        break_scope: region::Scope,
+        variable_scope_span: Span,
+    ) -> BlockAnd<()> {
         let this = self;
         let expr_span = expr.span;
 
         match expr.kind {
             ExprKind::Scope { region_scope, lint_level, value } => {
-                let region_scope = (region_scope, source_info);
-                let then_block;
-                let else_block = unpack!(
-                    then_block = this.in_scope(region_scope, lint_level, |this| {
-                        let (then_block, else_block) =
-                            this.then_else_blocks(block, &this.thir[value], scope, source_info);
-                        then_block.and(else_block)
-                    })
-                );
-                (then_block, else_block)
+                let region_scope = (region_scope, this.source_info(expr_span));
+                this.in_scope(region_scope, lint_level, |this| {
+                    this.then_else_break(
+                        block,
+                        &this.thir[value],
+                        temp_scope,
+                        break_scope,
+                        variable_scope_span,
+                    )
+                })
             }
             ExprKind::Let { expr, ref pat } => {
-                // FIXME: Use correct span.
-                this.lower_let(block, &this.thir[expr], pat, expr_span)
+                this.lower_let_expr(block, &this.thir[expr], pat, break_scope, variable_scope_span)
             }
             _ => {
                 let mutability = Mutability::Mut;
-                let place = unpack!(block = this.as_temp(block, Some(scope), expr, mutability));
+                let place =
+                    unpack!(block = this.as_temp(block, Some(temp_scope), expr, mutability));
                 let operand = Operand::Move(Place::from(place));
+
                 let then_block = this.cfg.start_new_block();
                 let else_block = this.cfg.start_new_block();
                 let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
+
+                let source_info = this.source_info(expr_span);
                 this.cfg.terminate(block, source_info, term);
-                (then_block, else_block)
+                this.break_for_else(else_block, break_scope, source_info);
+
+                then_block.unit()
             }
         }
     }
@@ -143,8 +149,15 @@ pub(crate) fn then_else_blocks(
         let mut candidates =
             arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
 
-        let fake_borrow_temps =
-            self.lower_match_tree(block, scrutinee_span, match_has_guard, &mut candidates);
+        let match_start_span = span.shrink_to_lo().to(scrutinee.span);
+
+        let fake_borrow_temps = self.lower_match_tree(
+            block,
+            scrutinee_span,
+            match_start_span,
+            match_has_guard,
+            &mut candidates,
+        );
 
         self.lower_match_arms(
             destination,
@@ -224,6 +237,7 @@ fn lower_match_tree<'pat>(
         &mut self,
         block: BasicBlock,
         scrutinee_span: Span,
+        match_start_span: Span,
         match_has_guard: bool,
         candidates: &mut [&mut Candidate<'pat, 'tcx>],
     ) -> Vec<(Place<'tcx>, Local)> {
@@ -236,7 +250,14 @@ fn lower_match_tree<'pat>(
 
         // This will generate code to test scrutinee_place and
         // branch to the appropriate arm block
-        self.match_candidates(scrutinee_span, block, &mut otherwise, candidates, &mut fake_borrows);
+        self.match_candidates(
+            match_start_span,
+            scrutinee_span,
+            block,
+            &mut otherwise,
+            candidates,
+            &mut fake_borrows,
+        );
 
         if let Some(otherwise_block) = otherwise {
             // See the doc comment on `match_candidates` for why we may have an
@@ -287,6 +308,7 @@ fn lower_match_arms(
 
                 let arm_source_info = self.source_info(arm.span);
                 let arm_scope = (arm.scope, arm_source_info);
+                let match_scope = self.local_scope();
                 self.in_scope(arm_scope, arm.lint_level, |this| {
                     // `try_upvars_resolved` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -325,6 +347,7 @@ fn lower_match_arms(
                         scrutinee_span,
                         Some(arm.span),
                         Some(arm.scope),
+                        Some(match_scope),
                     );
 
                     if let Some(source_scope) = scope {
@@ -339,8 +362,14 @@ fn lower_match_arms(
         // all the arm blocks will rejoin here
         let end_block = self.cfg.start_new_block();
 
+        let end_brace = self.source_info(
+            outer_source_info.span.with_lo(outer_source_info.span.hi() - BytePos::from_usize(1)),
+        );
         for arm_block in arm_end_blocks {
-            self.cfg.goto(unpack!(arm_block), outer_source_info, end_block);
+            let block = &self.cfg.basic_blocks[arm_block.0];
+            let last_location = block.statements.last().map(|s| s.source_info);
+
+            self.cfg.goto(unpack!(arm_block), last_location.unwrap_or(end_brace), end_block);
         }
 
         self.source_scope = outer_source_info.scope;
@@ -363,6 +392,7 @@ fn bind_pattern(
         scrutinee_span: Span,
         arm_span: Option<Span>,
         arm_scope: Option<region::Scope>,
+        match_scope: Option<region::Scope>,
     ) -> BasicBlock {
         if candidate.subcandidates.is_empty() {
             // Avoid generating another `BasicBlock` when we only have one
@@ -374,6 +404,7 @@ fn bind_pattern(
                 fake_borrow_temps,
                 scrutinee_span,
                 arm_span,
+                match_scope,
                 true,
             )
         } else {
@@ -410,6 +441,7 @@ fn bind_pattern(
                         &fake_borrow_temps,
                         scrutinee_span,
                         arm_span,
+                        match_scope,
                         schedule_drops,
                     );
                     if arm_scope.is_none() {
@@ -533,8 +565,13 @@ pub(super) fn expr_into_pattern(
         set_match_place: bool,
     ) -> BlockAnd<()> {
         let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false);
-        let fake_borrow_temps =
-            self.lower_match_tree(block, irrefutable_pat.span, false, &mut [&mut candidate]);
+        let fake_borrow_temps = self.lower_match_tree(
+            block,
+            irrefutable_pat.span,
+            irrefutable_pat.span,
+            false,
+            &mut [&mut candidate],
+        );
         // For matches and function arguments, the place that is being matched
         // can be set when creating the variables. But the place for
         // let PATTERN = ... might not even exist until we do the assignment.
@@ -590,6 +627,7 @@ pub(super) fn expr_into_pattern(
             irrefutable_pat.span,
             None,
             None,
+            None,
         )
         .unit()
     }
@@ -993,6 +1031,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn match_candidates<'pat>(
         &mut self,
         span: Span,
+        scrutinee_span: Span,
         start_block: BasicBlock,
         otherwise_block: &mut Option<BasicBlock>,
         candidates: &mut [&mut Candidate<'pat, 'tcx>],
@@ -1022,6 +1061,7 @@ fn match_candidates<'pat>(
                 }
                 self.match_simplified_candidates(
                     span,
+                    scrutinee_span,
                     start_block,
                     otherwise_block,
                     &mut *new_candidates,
@@ -1030,6 +1070,7 @@ fn match_candidates<'pat>(
             } else {
                 self.match_simplified_candidates(
                     span,
+                    scrutinee_span,
                     start_block,
                     otherwise_block,
                     candidates,
@@ -1042,6 +1083,7 @@ fn match_candidates<'pat>(
     fn match_simplified_candidates(
         &mut self,
         span: Span,
+        scrutinee_span: Span,
         start_block: BasicBlock,
         otherwise_block: &mut Option<BasicBlock>,
         candidates: &mut [&mut Candidate<'_, 'tcx>],
@@ -1087,6 +1129,7 @@ fn match_simplified_candidates(
         // Test for the remaining candidates.
         self.test_candidates_with_or(
             span,
+            scrutinee_span,
             unmatched_candidates,
             block,
             otherwise_block,
@@ -1257,6 +1300,7 @@ fn select_matched_candidates(
     fn test_candidates_with_or(
         &mut self,
         span: Span,
+        scrutinee_span: Span,
         candidates: &mut [&mut Candidate<'_, 'tcx>],
         block: BasicBlock,
         otherwise_block: &mut Option<BasicBlock>,
@@ -1269,7 +1313,14 @@ fn test_candidates_with_or(
         match *first_candidate.match_pairs[0].pattern.kind {
             PatKind::Or { .. } => (),
             _ => {
-                self.test_candidates(span, candidates, block, otherwise_block, fake_borrows);
+                self.test_candidates(
+                    span,
+                    scrutinee_span,
+                    candidates,
+                    block,
+                    otherwise_block,
+                    fake_borrows,
+                );
                 return;
             }
         }
@@ -1302,6 +1353,7 @@ fn test_candidates_with_or(
 
         self.match_candidates(
             span,
+            scrutinee_span,
             remainder_start,
             otherwise_block,
             remaining_candidates,
@@ -1330,6 +1382,7 @@ fn test_or_pattern<'pat>(
             otherwise
         };
         self.match_candidates(
+            or_span,
             or_span,
             candidate.pre_binding_block.unwrap(),
             otherwise,
@@ -1497,6 +1550,7 @@ fn merge_trivial_subcandidates(
     fn test_candidates<'pat, 'b, 'c>(
         &mut self,
         span: Span,
+        scrutinee_span: Span,
         mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
         block: BasicBlock,
         otherwise_block: &mut Option<BasicBlock>,
@@ -1591,6 +1645,7 @@ fn test_candidates<'pat, 'b, 'c>(
                         let candidate_start = this.cfg.start_new_block();
                         this.match_candidates(
                             span,
+                            scrutinee_span,
                             candidate_start,
                             remainder_start,
                             &mut *candidates,
@@ -1607,6 +1662,7 @@ fn test_candidates<'pat, 'b, 'c>(
                 let remainder_start = remainder_start.unwrap_or_else(|| this.cfg.start_new_block());
                 this.match_candidates(
                     span,
+                    scrutinee_span,
                     remainder_start,
                     otherwise_block,
                     candidates,
@@ -1617,7 +1673,7 @@ fn test_candidates<'pat, 'b, 'c>(
             target_blocks
         };
 
-        self.perform_test(block, match_place, &test, make_target_blocks);
+        self.perform_test(span, scrutinee_span, block, match_place, &test, make_target_blocks);
     }
 
     /// Determine the fake borrows that are needed from a set of places that
@@ -1698,13 +1754,14 @@ fn calculate_fake_borrows<'b>(
 // Pat binding - used for `let` and function parameters as well.
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn lower_let(
+    crate fn lower_let_expr(
         &mut self,
         mut block: BasicBlock,
         expr: &Expr<'tcx>,
         pat: &Pat<'tcx>,
+        else_target: region::Scope,
         span: Span,
-    ) -> (BasicBlock, BasicBlock) {
+    ) -> BlockAnd<()> {
         let expr_span = expr.span;
         let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
         let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
@@ -1713,6 +1770,7 @@ pub fn lower_let(
         let fake_borrow_temps = self.lower_match_tree(
             block,
             pat.span,
+            pat.span,
             false,
             &mut [&mut guard_candidate, &mut otherwise_candidate],
         );
@@ -1724,6 +1782,9 @@ pub fn lower_let(
             expr_place = expr_builder.into_place(self.tcx, self.typeck_results);
             opt_expr_place = Some((Some(&expr_place), expr_span));
         }
+        let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
+        self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
+
         self.declare_bindings(None, pat.span.to(span), pat, ArmHasGuard(false), opt_expr_place);
         let post_guard_block = self.bind_pattern(
             self.source_info(pat.span),
@@ -1733,9 +1794,10 @@ pub fn lower_let(
             expr.span,
             None,
             None,
+            None,
         );
-        let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
-        (post_guard_block, otherwise_post_guard_block)
+
+        post_guard_block.unit()
     }
 
     /// Initializes each of the bindings from the candidate by
@@ -1754,6 +1816,7 @@ fn bind_and_guard_matched_candidate<'pat>(
         fake_borrows: &Vec<(Place<'tcx>, Local)>,
         scrutinee_span: Span,
         arm_span: Option<Span>,
+        match_scope: Option<region::Scope>,
         schedule_drops: bool,
     ) -> BasicBlock {
         debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate);
@@ -1884,17 +1947,25 @@ fn bind_and_guard_matched_candidate<'pat>(
                 self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
             }
 
-            let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match *guard {
-                Guard::If(e) => {
-                    let e = &self.thir[e];
-                    let source_info = self.source_info(e.span);
-                    (e.span, self.test_bool(block, e, source_info))
-                }
-                Guard::IfLet(ref pat, scrutinee) => {
-                    let s = &self.thir[scrutinee];
-                    (s.span, self.lower_let(block, s, pat, arm_span.unwrap()))
-                }
-            };
+            let arm_span = arm_span.unwrap();
+            let arm_scope = self.local_scope();
+            let match_scope = match_scope.unwrap();
+            let mut guard_span = rustc_span::DUMMY_SP;
+
+            let (post_guard_block, otherwise_post_guard_block) =
+                self.in_if_then_scope(match_scope, |this| match *guard {
+                    Guard::If(e) => {
+                        let e = &this.thir[e];
+                        guard_span = e.span;
+                        this.then_else_break(block, e, arm_scope, match_scope, arm_span)
+                    }
+                    Guard::IfLet(ref pat, scrutinee) => {
+                        let s = &this.thir[scrutinee];
+                        guard_span = s.span;
+                        this.lower_let_expr(block, s, pat, match_scope, arm_span)
+                    }
+                });
+
             let source_info = self.source_info(guard_span);
             let guard_end = self.source_info(tcx.sess.source_map().end_point(guard_span));
             let guard_frame = self.guard_context.pop().unwrap();
@@ -1910,10 +1981,8 @@ fn bind_and_guard_matched_candidate<'pat>(
                 self.cfg.terminate(unreachable, source_info, TerminatorKind::Unreachable);
                 unreachable
             });
-            let outside_scope = self.cfg.start_new_block();
-            self.exit_top_scope(otherwise_post_guard_block, outside_scope, source_info);
             self.false_edges(
-                outside_scope,
+                otherwise_post_guard_block,
                 otherwise_block,
                 candidate.next_candidate_pre_binding_block,
                 source_info,
index 42d062c93e9d2e79763f80a3293f86f97b700845..a01df2372a0978499de8349d31b81ab467252f02 100644 (file)
@@ -19,6 +19,7 @@
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_span::Span;
 use rustc_target::abi::VariantIdx;
 
 use std::cmp::Ordering;
@@ -151,6 +152,8 @@ pub(super) fn add_variants_to_switch<'pat>(
 
     pub(super) fn perform_test(
         &mut self,
+        match_start_span: Span,
+        scrutinee_span: Span,
         block: BasicBlock,
         place_builder: PlaceBuilder<'tcx>,
         test: &Test<'tcx>,
@@ -206,10 +209,15 @@ pub(super) fn perform_test(
                 debug!("num_enum_variants: {}, variants: {:?}", num_enum_variants, variants);
                 let discr_ty = adt_def.repr.discr_type().to_ty(tcx);
                 let discr = self.temp(discr_ty, test.span);
-                self.cfg.push_assign(block, source_info, discr, Rvalue::Discriminant(place));
+                self.cfg.push_assign(
+                    block,
+                    self.source_info(scrutinee_span),
+                    discr,
+                    Rvalue::Discriminant(place),
+                );
                 self.cfg.terminate(
                     block,
-                    source_info,
+                    self.source_info(match_start_span),
                     TerminatorKind::SwitchInt {
                         discr: Operand::Move(discr),
                         switch_ty: discr_ty,
@@ -246,7 +254,7 @@ pub(super) fn perform_test(
                         targets: switch_targets,
                     }
                 };
-                self.cfg.terminate(block, source_info, terminator);
+                self.cfg.terminate(block, self.source_info(match_start_span), terminator);
             }
 
             TestKind::Eq { value, ty } => {
index bfebe860971e9f8e28e6973c503e8a3d83357140..0a760a740dcaea5801a8b4bcb854d19ba6758d50 100644 (file)
@@ -239,10 +239,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
         // The exception is `body.user_type_annotations`, which is used unmodified
         // by borrow checking.
         debug_assert!(
-            !(body.local_decls.has_free_regions()
-                || body.basic_blocks().has_free_regions()
-                || body.var_debug_info.has_free_regions()
-                || body.yield_ty().has_free_regions()),
+            !(body.local_decls.has_free_regions(tcx)
+                || body.basic_blocks().has_free_regions(tcx)
+                || body.var_debug_info.has_free_regions(tcx)
+                || body.yield_ty().has_free_regions(tcx)),
             "Unexpected free regions in MIR: {:?}",
             body,
         );
@@ -755,6 +755,7 @@ fn construct_error<'a, 'tcx>(
     cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
 
     let mut body = Body::new(
+        tcx,
         MirSource::item(def.did.to_def_id()),
         cfg.basic_blocks,
         source_scopes,
@@ -843,6 +844,7 @@ fn finish(self) -> Body<'tcx> {
         }
 
         Body::new(
+            self.tcx,
             MirSource::item(self.def_id),
             self.cfg.basic_blocks,
             self.source_scopes,
index 496db58758cdcc18b33c964a98a6e93846107a79..bd8d14fcd012c2ec5965940a517e50b568c234ef 100644 (file)
@@ -81,6 +81,8 @@
 
 */
 
+use std::mem;
+
 use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::IndexVec;
 #[derive(Debug)]
 pub struct Scopes<'tcx> {
     scopes: Vec<Scope>,
+
     /// The current set of breakable scopes. See module comment for more details.
     breakable_scopes: Vec<BreakableScope<'tcx>>,
 
+    /// The scope of the innermost if-then currently being lowered.
+    if_then_scope: Option<IfThenScope>,
+
     /// Drops that need to be done on unwind paths. See the comment on
     /// [DropTree] for more details.
     unwind_drops: DropTree,
@@ -164,6 +170,14 @@ struct BreakableScope<'tcx> {
     continue_drops: Option<DropTree>,
 }
 
+#[derive(Debug)]
+struct IfThenScope {
+    /// The if-then scope or arm scope
+    region_scope: region::Scope,
+    /// Drops that happen on the `else` path.
+    else_drops: DropTree,
+}
+
 /// The target of an expression that breaks out of a scope
 #[derive(Clone, Copy, Debug)]
 crate enum BreakableTarget {
@@ -183,6 +197,7 @@ struct DropIdx { .. }
 /// * Drops on unwind paths
 /// * Drops on generator drop paths (when a suspended generator is dropped)
 /// * Drops on return and loop exit paths
+/// * Drops on the else path in an `if let` chain
 ///
 /// Once no more nodes could be added to the tree, we lower it to MIR in one go
 /// in `build_mir`.
@@ -394,6 +409,7 @@ pub(crate) fn new() -> Self {
         Self {
             scopes: Vec::new(),
             breakable_scopes: Vec::new(),
+            if_then_scope: None,
             unwind_drops: DropTree::new(),
             generator_drops: DropTree::new(),
         }
@@ -483,6 +499,45 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    /// Start an if-then scope which tracks drop for `if` expressions and `if`
+    /// guards.
+    ///
+    /// For an if-let chain:
+    ///
+    /// if let Some(x) = a && let Some(y) = b && let Some(z) = c { ... }
+    ///
+    /// there are three possible ways the condition can be false and we may have
+    /// to drop `x`, `x` and `y`, or neither depending on which binding fails.
+    /// To handle this correctly we use a `DropTree` in a similar way to a
+    /// `loop` expression and 'break' out on all of the 'else' paths.
+    ///
+    /// Notes:
+    /// - We don't need to keep a stack of scopes in the `Builder` because the
+    ///   'else' paths will only leave the innermost scope.
+    /// - This is also used for match guards.
+    crate fn in_if_then_scope<F>(
+        &mut self,
+        region_scope: region::Scope,
+        f: F,
+    ) -> (BasicBlock, BasicBlock)
+    where
+        F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<()>,
+    {
+        let scope = IfThenScope { region_scope, else_drops: DropTree::new() };
+        let previous_scope = mem::replace(&mut self.scopes.if_then_scope, Some(scope));
+
+        let then_block = unpack!(f(self));
+
+        let if_then_scope = mem::replace(&mut self.scopes.if_then_scope, previous_scope).unwrap();
+        assert!(if_then_scope.region_scope == region_scope);
+
+        let else_block = self
+            .build_exit_tree(if_then_scope.else_drops, None)
+            .map_or_else(|| self.cfg.start_new_block(), |else_block_and| unpack!(else_block_and));
+
+        (then_block, else_block)
+    }
+
     crate fn in_opt_scope<F, R>(
         &mut self,
         opt_scope: Option<(region::Scope, SourceInfo)>,
@@ -651,6 +706,36 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.start_new_block().unit()
     }
 
+    crate fn break_for_else(
+        &mut self,
+        block: BasicBlock,
+        target: region::Scope,
+        source_info: SourceInfo,
+    ) {
+        let scope_index = self.scopes.scope_index(target, source_info.span);
+        let if_then_scope = self
+            .scopes
+            .if_then_scope
+            .as_mut()
+            .unwrap_or_else(|| span_bug!(source_info.span, "no if-then scope found"));
+
+        assert_eq!(if_then_scope.region_scope, target, "breaking to incorrect scope");
+
+        let mut drop_idx = ROOT_NODE;
+        let drops = &mut if_then_scope.else_drops;
+        for scope in &self.scopes.scopes[scope_index + 1..] {
+            for drop in &scope.drops {
+                drop_idx = drops.add_drop(*drop, drop_idx);
+            }
+        }
+        drops.add_entry(block, drop_idx);
+
+        // `build_drop_tree` doesn't have access to our source_info, so we
+        // create a dummy terminator now. `TerminatorKind::Resume` is used
+        // because MIR type checking will panic if it hasn't been overwritten.
+        self.cfg.terminate(block, source_info, TerminatorKind::Resume);
+    }
+
     // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
     // statement.
     fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info: SourceInfo) {
@@ -659,16 +744,6 @@ fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info:
         self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
     }
 
-    crate fn exit_top_scope(
-        &mut self,
-        mut block: BasicBlock,
-        target: BasicBlock,
-        source_info: SourceInfo,
-    ) {
-        block = self.leave_top_scope(block);
-        self.cfg.terminate(block, source_info, TerminatorKind::Goto { target });
-    }
-
     fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
         // If we are emitting a `drop` statement, we need to have the cached
         // diverge cleanup pads ready in case that drop panics.
@@ -927,61 +1002,6 @@ fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
 
     // Other
     // =====
-    /// Branch based on a boolean condition.
-    ///
-    /// This is a special case because the temporary for the condition needs to
-    /// be dropped on both the true and the false arm.
-    crate fn test_bool(
-        &mut self,
-        mut block: BasicBlock,
-        condition: &Expr<'tcx>,
-        source_info: SourceInfo,
-    ) -> (BasicBlock, BasicBlock) {
-        let cond = unpack!(block = self.as_local_operand(block, condition));
-        let true_block = self.cfg.start_new_block();
-        let false_block = self.cfg.start_new_block();
-        let term = TerminatorKind::if_(self.tcx, cond.clone(), true_block, false_block);
-        self.cfg.terminate(block, source_info, term);
-
-        match cond {
-            // Don't try to drop a constant
-            Operand::Constant(_) => (),
-            Operand::Copy(place) | Operand::Move(place) => {
-                if let Some(cond_temp) = place.as_local() {
-                    // Manually drop the condition on both branches.
-                    let top_scope = self.scopes.scopes.last_mut().unwrap();
-                    let top_drop_data = top_scope.drops.pop().unwrap();
-                    if self.generator_kind.is_some() {
-                        top_scope.invalidate_cache();
-                    }
-
-                    match top_drop_data.kind {
-                        DropKind::Value { .. } => {
-                            bug!("Drop scheduled on top of condition variable")
-                        }
-                        DropKind::Storage => {
-                            let source_info = top_drop_data.source_info;
-                            let local = top_drop_data.local;
-                            assert_eq!(local, cond_temp, "Drop scheduled on top of condition");
-                            self.cfg.push(
-                                true_block,
-                                Statement { source_info, kind: StatementKind::StorageDead(local) },
-                            );
-                            self.cfg.push(
-                                false_block,
-                                Statement { source_info, kind: StatementKind::StorageDead(local) },
-                            );
-                        }
-                    }
-                } else {
-                    bug!("Expected as_local_operand to produce a temporary");
-                }
-            }
-        }
-
-        (true_block, false_block)
-    }
-
     /// Returns the [DropIdx] for the innermost drop if the function unwound at
     /// this point. The `DropIdx` will be created if it doesn't already exist.
     fn diverge_cleanup(&mut self) -> DropIdx {
index f1d882e1ddd7055d06e7b3e45aa99536e16620ab..66005be05df75683ba3427c2c9719262317287fc 100644 (file)
@@ -594,6 +594,10 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
                 ExprKind::Let { expr: self.mirror_expr(expr), pat: self.pattern_from_hir(pat) }
             }
             hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
+                if_then_scope: region::Scope {
+                    id: then.hir_id.local_id,
+                    data: region::ScopeData::IfThen,
+                },
                 cond: self.mirror_expr(cond),
                 then: self.mirror_expr(then),
                 else_opt: else_opt.map(|el| self.mirror_expr(el)),
@@ -693,11 +697,10 @@ fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx>
                                 // and not the beginning of discriminants (which is always `0`)
                                 let substs = InternalSubsts::identity_for_item(self.tcx(), did);
                                 let lhs = ty::Const {
-                                    val: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                                        def: ty::WithOptConstParam::unknown(did),
+                                    val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
+                                        ty::WithOptConstParam::unknown(did),
                                         substs,
-                                        promoted: None,
-                                    }),
+                                    )),
                                     ty: var_ty,
                                 };
                                 let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
@@ -889,11 +892,10 @@ fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKi
                 debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
                 ExprKind::Literal {
                     literal: self.tcx.mk_const(ty::Const {
-                        val: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                            def: ty::WithOptConstParam::unknown(def_id),
+                        val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(
+                            ty::WithOptConstParam::unknown(def_id),
                             substs,
-                            promoted: None,
-                        }),
+                        )),
                         ty: self.typeck_results().node_type(expr.hir_id),
                     }),
                     user_ty,
index 50cbe0f71f552837c691295bf05eb7473156931f..b34c1e07be71c61ff6d2673d67e1ea2bfe1509e6 100644 (file)
@@ -17,7 +17,7 @@
 use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
 use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
 use rustc_session::Session;
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, ExpnKind, Span};
 use std::slice;
 
 crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
@@ -118,31 +118,6 @@ fn check_patterns(&self, pat: &Pat<'_>) {
         check_for_bindings_named_same_as_variants(self, pat);
     }
 
-    fn let_source(&mut self, pat: &'tcx hir::Pat<'tcx>, _expr: &hir::Expr<'_>) -> LetSource {
-        let hir = self.tcx.hir();
-        let parent = hir.get_parent_node(pat.hir_id);
-        let parent_parent = hir.get_parent_node(parent);
-        let parent_parent_node = hir.get(parent_parent);
-
-        let parent_parent_parent = hir.get_parent_node(parent_parent);
-        let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent);
-        let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
-
-        if let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
-            ..
-        }) = parent_parent_parent_parent_node
-        {
-            LetSource::WhileLet
-        } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If { .. }, .. }) =
-            parent_parent_node
-        {
-            LetSource::IfLet
-        } else {
-            LetSource::GenericLet
-        }
-    }
-
     fn lower_pattern<'p>(
         &self,
         cx: &mut MatchCheckCtxt<'p, 'tcx>,
@@ -172,10 +147,9 @@ fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'_, 'tcx> {
 
     fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) {
         self.check_patterns(pat);
-        let ls = self.let_source(pat, expr);
         let mut cx = self.new_cx(expr.hir_id);
         let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
-        check_let_reachability(&mut cx, ls, pat.hir_id, &tpat, span);
+        check_let_reachability(&mut cx, pat.hir_id, &tpat, span);
     }
 
     fn check_match(
@@ -192,13 +166,7 @@ fn check_match(
             if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
                 self.check_patterns(pat);
                 let tpat = self.lower_pattern(&mut cx, pat, &mut false).0;
-                check_let_reachability(
-                    &mut cx,
-                    LetSource::IfLetGuard,
-                    pat.hir_id,
-                    &tpat,
-                    tpat.span,
-                );
+                check_let_reachability(&mut cx, pat.hir_id, &tpat, tpat.span);
             }
         }
 
@@ -397,7 +365,7 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
     });
 }
 
-fn irrefutable_let_pattern(id: HirId, ls: LetSource, span: Span, tcx: TyCtxt<'_>) {
+fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
     macro_rules! emit_diag {
         (
             $lint:expr,
@@ -412,7 +380,12 @@ macro_rules! emit_diag {
         }};
     }
 
-    tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match ls {
+    let source = let_source(tcx, id);
+    let span = match source {
+        LetSource::LetElse(span) => span,
+        _ => span,
+    };
+    tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
         LetSource::GenericLet => {
             emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
         }
@@ -432,6 +405,14 @@ macro_rules! emit_diag {
                 "removing the guard and adding a `let` inside the match arm"
             );
         }
+        LetSource::LetElse(..) => {
+            emit_diag!(
+                lint,
+                "`let...else`",
+                "`else` clause is useless",
+                "removing the `else` clause"
+            );
+        }
         LetSource::WhileLet => {
             emit_diag!(
                 lint,
@@ -445,7 +426,6 @@ macro_rules! emit_diag {
 
 fn check_let_reachability<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
-    ls: LetSource,
     pat_id: HirId,
     pat: &'p super::Pat<'tcx>,
     span: Span,
@@ -454,13 +434,13 @@ fn check_let_reachability<'p, 'tcx>(
     let report = compute_match_usefulness(&cx, &arms, pat_id, pat.ty);
 
     report_arm_reachability(&cx, &report, |arm_index, arm_span, arm_hir_id, _| {
-        match ls {
+        match let_source(cx.tcx, pat_id) {
             LetSource::IfLet | LetSource::WhileLet => {
                 match arm_index {
                     // The arm with the user-specified pattern.
                     0 => unreachable_pattern(cx.tcx, arm_span, arm_hir_id, None),
                     // The arm with the wildcard pattern.
-                    1 => irrefutable_let_pattern(pat_id, ls, arm_span, cx.tcx),
+                    1 => irrefutable_let_pattern(cx.tcx, pat_id, arm_span),
                     _ => bug!(),
                 }
             }
@@ -473,7 +453,7 @@ fn check_let_reachability<'p, 'tcx>(
 
     if report.non_exhaustiveness_witnesses.is_empty() {
         // The match is exhaustive, i.e. the `if let` pattern is irrefutable.
-        irrefutable_let_pattern(pat_id, ls, span, cx.tcx);
+        irrefutable_let_pattern(cx.tcx, pat_id, span);
     }
 }
 
@@ -787,5 +767,46 @@ pub enum LetSource {
     GenericLet,
     IfLet,
     IfLetGuard,
+    LetElse(Span),
     WhileLet,
 }
+
+fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
+    let hir = tcx.hir();
+    let parent = hir.get_parent_node(pat_id);
+    match hir.get(parent) {
+        hir::Node::Arm(hir::Arm {
+            guard: Some(hir::Guard::IfLet(&hir::Pat { hir_id, .. }, _)),
+            ..
+        }) if hir_id == pat_id => {
+            return LetSource::IfLetGuard;
+        }
+        hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Let(..), span, .. }) => {
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(DesugaringKind::LetElse) = expn_data.kind {
+                return LetSource::LetElse(expn_data.call_site);
+            }
+        }
+        _ => {}
+    }
+    let parent_parent = hir.get_parent_node(parent);
+    let parent_parent_node = hir.get(parent_parent);
+
+    let parent_parent_parent = hir.get_parent_node(parent_parent);
+    let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent);
+    let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
+
+    if let hir::Node::Expr(hir::Expr {
+        kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
+        ..
+    }) = parent_parent_parent_parent_node
+    {
+        LetSource::WhileLet
+    } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If { .. }, .. }) =
+        parent_parent_node
+    {
+        LetSource::IfLet
+    } else {
+        LetSource::GenericLet
+    }
+}
index 926bd830da0ac470afcf1d1661569da560b1b789..bbb5de34d1860a84011421cfebb78e1130a76488 100644 (file)
@@ -237,7 +237,7 @@ fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
         // code at the moment, because types like `for <'a> fn(&'a ())` do
         // not *yet* implement `PartialEq`. So for now we leave this here.
         has_impl
-            || ty.walk().any(|t| match t.unpack() {
+            || ty.walk(self.tcx()).any(|t| match t.unpack() {
                 ty::subst::GenericArgKind::Lifetime(_) => false,
                 ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(),
                 ty::subst::GenericArgKind::Const(_) => false,
index 5221ced1078b37ec5752b11f70d55f5e8a868d3e..cb74ae4df2ef86ac4084583730a0d4343f20307e 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_middle::mir::{BorrowKind, Field, Mutability};
 use rustc_middle::thir::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
-use rustc_middle::ty::{self, AdtDef, DefIdTree, Region, Ty, TyCtxt, UserType};
+use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType};
 use rustc_span::{Span, Symbol};
 
 use std::cmp::Ordering;
@@ -545,6 +545,11 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
                 hir::ExprKind::ConstBlock(ref anon_const) => {
                     let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
                     let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
+                    if matches!(value.val, ConstKind::Param(_)) {
+                        let span = self.tcx.hir().span(anon_const.hir_id);
+                        self.errors.push(PatternError::ConstParamInPattern(span));
+                        return PatKind::Wild;
+                    }
                     return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind;
                 }
                 hir::ExprKind::Lit(ref lit) => (lit, false),
index dda6c74d4decad0652f899684e7f50fe60491ec2..51c371b872057ad2a440c91df342438f8ad2c1b3 100644 (file)
@@ -34,7 +34,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
             visitor.visit_expr(&visitor.thir()[value])
         }
         Box { value } => visitor.visit_expr(&visitor.thir()[value]),
-        If { cond, then, else_opt } => {
+        If { cond, then, else_opt, if_then_scope: _ } => {
             visitor.visit_expr(&visitor.thir()[cond]);
             visitor.visit_expr(&visitor.thir()[then]);
             if let Some(else_expr) = else_opt {
index 07f972c2fa897e0625ff90b00f91fb810146fbfb..bf76dedd252ca59cd021178e92bf1543c8bc0b15 100644 (file)
@@ -2,8 +2,10 @@
 
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
+#![feature(if_let_guard)]
 #![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(box_patterns)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 use rustc_ast as ast;
@@ -188,7 +190,7 @@ pub fn maybe_file_to_stream(
     let src = source_file.src.as_ref().unwrap_or_else(|| {
         sess.span_diagnostic.bug(&format!(
             "cannot lex `source_file` without source: {}",
-            source_file.name.prefer_local()
+            sess.source_map().filename_for_diagnostics(&source_file.name)
         ));
     });
 
@@ -262,20 +264,17 @@ pub fn nt_to_tokenstream(
     let tokens = match *nt {
         Nonterminal::NtItem(ref item) => prepend_attrs(&item.attrs, item.tokens.as_ref()),
         Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()),
-        Nonterminal::NtStmt(ref stmt) => {
-            if let ast::StmtKind::Empty = stmt.kind {
-                let tokens = AttrAnnotatedTokenStream::new(vec![(
-                    tokenstream::AttrAnnotatedTokenTree::Token(Token::new(
-                        TokenKind::Semi,
-                        stmt.span,
-                    )),
-                    Spacing::Alone,
-                )]);
-                prepend_attrs(&stmt.attrs(), Some(&LazyTokenStream::new(tokens)))
-            } else {
-                prepend_attrs(&stmt.attrs(), stmt.tokens())
-            }
+        Nonterminal::NtStmt(ref stmt) if let ast::StmtKind::Empty = stmt.kind => {
+            let tokens = AttrAnnotatedTokenStream::new(vec![(
+                tokenstream::AttrAnnotatedTokenTree::Token(Token::new(
+                    TokenKind::Semi,
+                    stmt.span,
+                )),
+                Spacing::Alone,
+            )]);
+            prepend_attrs(&stmt.attrs(), Some(&LazyTokenStream::new(tokens)))
         }
+        Nonterminal::NtStmt(ref stmt) => prepend_attrs(&stmt.attrs(), stmt.tokens()),
         Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()),
         Nonterminal::NtTy(ref ty) => convert_tokens(ty.tokens.as_ref()),
         Nonterminal::NtIdent(ident, is_raw) => {
index e9f0038b2d65dc9d09b763c3ae596d4fb8212e6d..b402b8ba53ada3b3a0a96e3307e6185f5b2ccbf1 100644 (file)
@@ -1,10 +1,10 @@
-use super::{AttrWrapper, Capturing, Parser, PathStyle};
+use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle};
 use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{error_code, PResult};
-use rustc_span::{sym, Span};
+use rustc_errors::{error_code, DiagnosticBuilder, PResult};
+use rustc_span::{sym, BytePos, Span};
 use std::convert::TryInto;
 
 use tracing::debug;
@@ -25,6 +25,12 @@ pub enum InnerAttrPolicy<'a> {
     prev_attr_sp: None,
 };
 
+enum OuterAttributeType {
+    DocComment,
+    DocBlockComment,
+    Attribute,
+}
+
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
@@ -49,18 +55,32 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
                 Some(self.parse_attribute(inner_parse_policy)?)
             } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                 if attr_style != ast::AttrStyle::Outer {
-                    self.sess
-                        .span_diagnostic
-                        .struct_span_err_with_code(
-                            self.token.span,
-                            "expected outer doc comment",
-                            error_code!(E0753),
-                        )
-                        .note(
-                            "inner doc comments like this (starting with \
-                         `//!` or `/*!`) can only appear before items",
-                        )
-                        .emit();
+                    let span = self.token.span;
+                    let mut err = self.sess.span_diagnostic.struct_span_err_with_code(
+                        span,
+                        "expected outer doc comment",
+                        error_code!(E0753),
+                    );
+                    if let Some(replacement_span) = self.annotate_following_item_if_applicable(
+                        &mut err,
+                        span,
+                        match comment_kind {
+                            token::CommentKind::Line => OuterAttributeType::DocComment,
+                            token::CommentKind::Block => OuterAttributeType::DocBlockComment,
+                        },
+                    ) {
+                        err.note(
+                            "inner doc comments like this (starting with `//!` or `/*!`) can \
+                            only appear before items",
+                        );
+                        err.span_suggestion_verbose(
+                            replacement_span,
+                            "you might have meant to write a regular comment",
+                            String::new(),
+                            rustc_errors::Applicability::MachineApplicable,
+                        );
+                    }
+                    err.emit();
                 }
                 self.bump();
                 just_parsed_doc_comment = true;
@@ -97,7 +117,7 @@ pub fn parse_attribute(
             inner_parse_policy, self.token
         );
         let lo = self.token.span;
-        // Attributse can't have attributes of their own
+        // Attributes can't have attributes of their own [Editor's note: not with that attitude]
         self.collect_tokens_no_attrs(|this| {
             if this.eat(&token::Pound) {
                 let style = if this.eat(&token::Not) {
@@ -125,6 +145,75 @@ pub fn parse_attribute(
         })
     }
 
+    fn annotate_following_item_if_applicable(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        span: Span,
+        attr_type: OuterAttributeType,
+    ) -> Option<Span> {
+        let mut snapshot = self.clone();
+        let lo = span.lo()
+            + BytePos(match attr_type {
+                OuterAttributeType::Attribute => 1,
+                _ => 2,
+            });
+        let hi = lo + BytePos(1);
+        let replacement_span = span.with_lo(lo).with_hi(hi);
+        if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type {
+            snapshot.bump();
+        }
+        loop {
+            // skip any other attributes, we want the item
+            if snapshot.token.kind == token::Pound {
+                if let Err(mut err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) {
+                    err.cancel();
+                    return Some(replacement_span);
+                }
+            } else {
+                break;
+            }
+        }
+        match snapshot.parse_item_common(
+            AttrWrapper::empty(),
+            true,
+            false,
+            |_| true,
+            ForceCollect::No,
+        ) {
+            Ok(Some(item)) => {
+                let attr_name = match attr_type {
+                    OuterAttributeType::Attribute => "attribute",
+                    _ => "doc comment",
+                };
+                err.span_label(
+                    item.span,
+                    &format!("the inner {} doesn't annotate this {}", attr_name, item.kind.descr()),
+                );
+                err.span_suggestion_verbose(
+                    replacement_span,
+                    &format!(
+                        "to annotate the {}, change the {} from inner to outer style",
+                        item.kind.descr(),
+                        attr_name
+                    ),
+                    (match attr_type {
+                        OuterAttributeType::Attribute => "",
+                        OuterAttributeType::DocBlockComment => "*",
+                        OuterAttributeType::DocComment => "/",
+                    })
+                    .to_string(),
+                    rustc_errors::Applicability::MachineApplicable,
+                );
+                return None;
+            }
+            Err(mut item_err) => {
+                item_err.cancel();
+            }
+            Ok(None) => {}
+        }
+        Some(replacement_span)
+    }
+
     pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
         if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_attr_sp } = policy {
             let prev_attr_note =
@@ -138,11 +227,20 @@ pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerA
             }
 
             diag.note(
-                "inner attributes, like `#![no_std]`, annotate the item enclosing them, \
-                and are usually found at the beginning of source files. \
-                Outer attributes, like `#[test]`, annotate the item following them.",
-            )
-            .emit();
+                "inner attributes, like `#![no_std]`, annotate the item enclosing them, and \
+                are usually found at the beginning of source files",
+            );
+            if self
+                .annotate_following_item_if_applicable(
+                    &mut diag,
+                    attr_sp,
+                    OuterAttributeType::Attribute,
+                )
+                .is_some()
+            {
+                diag.note("outer attributes, like `#[test]`, annotate the item following them");
+            };
+            diag.emit();
         }
     }
 
index 273fbea3580216d051566ccd5c3d56fcfcad869c..94ca70d3f9578efa2020fb58d222cd6f8981cf80 100644 (file)
@@ -446,11 +446,13 @@ pub fn maybe_suggest_struct_literal(
                         )
                         .emit();
                     *self = snapshot;
-                    Ok(self.mk_block(
+                    let mut tail = self.mk_block(
                         vec![self.mk_stmt_err(expr.span)],
                         s,
                         lo.to(self.prev_token.span),
-                    ))
+                    );
+                    tail.could_be_bare_literal = true;
+                    Ok(tail)
                 }
                 (Err(mut err), Ok(tail)) => {
                     // We have a block tail that contains a somehow valid type ascription expr.
@@ -463,7 +465,10 @@ pub fn maybe_suggest_struct_literal(
                     self.consume_block(token::Brace, ConsumeClosingDelim::Yes);
                     Err(err)
                 }
-                (Ok(_), Ok(tail)) => Ok(tail),
+                (Ok(_), Ok(mut tail)) => {
+                    tail.could_be_bare_literal = true;
+                    Ok(tail)
+                }
             });
         }
         None
@@ -1432,12 +1437,22 @@ pub(super) fn recover_closing_delimiter(
                 // the most sense, which is immediately after the last token:
                 //
                 //  {foo(bar {}}
-                //      -      ^
+                //      ^      ^
                 //      |      |
                 //      |      help: `)` may belong here
                 //      |
                 //      unclosed delimiter
                 if let Some(sp) = unmatched.unclosed_span {
+                    let mut primary_span: Vec<Span> =
+                        err.span.primary_spans().iter().cloned().collect();
+                    primary_span.push(sp);
+                    let mut primary_span: MultiSpan = primary_span.into();
+                    for span_label in err.span.span_labels() {
+                        if let Some(label) = span_label.label {
+                            primary_span.push_span_label(span_label.span, label);
+                        }
+                    }
+                    err.set_span(primary_span);
                     err.span_label(sp, "unclosed delimiter");
                 }
                 // Backticks should be removed to apply suggestions.
index 326c8f81ffbf9f64973bfbddaa7c3efadcbc17a0..a1d3e9adba013e91d0ecd36745bd928bac6d32cf 100644 (file)
@@ -41,7 +41,7 @@ macro_rules! maybe_whole_expr {
                     let path = path.clone();
                     $p.bump();
                     return Ok($p.mk_expr(
-                        $p.token.span,
+                        $p.prev_token.span,
                         ExprKind::Path(None, path),
                         AttrVec::new(),
                     ));
@@ -50,7 +50,7 @@ macro_rules! maybe_whole_expr {
                     let block = block.clone();
                     $p.bump();
                     return Ok($p.mk_expr(
-                        $p.token.span,
+                        $p.prev_token.span,
                         ExprKind::Block(block, None),
                         AttrVec::new(),
                     ));
@@ -1528,7 +1528,7 @@ fn error_float_lits_must_have_int_part(&self, token: &Token) {
             .span_suggestion(
                 token.span,
                 "must have an integer part",
-                pprust::token_to_string(token),
+                pprust::token_to_string(token).into(),
                 Applicability::MachineApplicable,
             )
             .emit();
index e5537d43ebaa1ef7c5225dc3861cce7ac3b5932f..10c73fd64bc198cece7158a1ea964629b8d985d8 100644 (file)
@@ -26,8 +26,7 @@ impl<'a> Parser<'a> {
     /// Parses a source module as a crate. This is the main entry point for the parser.
     pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> {
         let (attrs, items, span) = self.parse_mod(&token::Eof)?;
-        let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`.
-        Ok(ast::Crate { attrs, items, span, proc_macros })
+        Ok(ast::Crate { attrs, items, span })
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
index 4c3c140d17100a8fd00d6107d296ea7b5feb1571..c4419e995edac84940900418d87186aecdb89235 100644 (file)
@@ -33,7 +33,7 @@
 use rustc_errors::PResult;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError};
 use rustc_session::parse::ParseSess;
-use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_span::source_map::{MultiSpan, Span, DUMMY_SP};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use tracing::debug;
 
@@ -806,7 +806,7 @@ fn parse_seq_to_before_tokens<T>(
                                         .span_suggestion_short(
                                             sp,
                                             &format!("missing `{}`", token_str),
-                                            token_str,
+                                            token_str.into(),
                                             Applicability::MaybeIncorrect,
                                         )
                                         .emit();
@@ -1335,8 +1335,13 @@ pub fn clear_expected_tokens(&mut self) {
     // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
     // `unmatched_braces` only for error recovery in the `Parser`.
     let found_delim = unmatched.found_delim?;
+    let span: MultiSpan = if let Some(sp) = unmatched.unclosed_span {
+        vec![unmatched.found_span, sp].into()
+    } else {
+        unmatched.found_span.into()
+    };
     let mut err = sess.span_diagnostic.struct_span_err(
-        unmatched.found_span,
+        span,
         &format!(
             "mismatched closing delimiter: `{}`",
             pprust::token_kind_to_string(&token::CloseDelim(found_delim)),
index 313d9db58fc3febec5eb8010f23fd02cdb2f589e..72e6f8a1bc8574121c0e8e9d610da8d0e78307db 100644 (file)
@@ -143,15 +143,16 @@ pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, Nonter
                 token::NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty())?)
             }
             // this could be handled like a token, since it is one
+            NonterminalKind::Ident
+                if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
+            {
+                self.bump();
+                token::NtIdent(ident, is_raw)
+            }
             NonterminalKind::Ident => {
-                if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
-                    self.bump();
-                    token::NtIdent(ident, is_raw)
-                } else {
-                    let token_str = pprust::token_to_string(&self.token);
-                    let msg = &format!("expected ident, found {}", &token_str);
-                    return Err(self.struct_span_err(self.token.span, msg));
-                }
+                let token_str = pprust::token_to_string(&self.token);
+                let msg = &format!("expected ident, found {}", &token_str);
+                return Err(self.struct_span_err(self.token.span, msg));
             }
             NonterminalKind::Path => token::NtPath(
                 self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
index 9ef3f61ec346b11b2933dcc5f0cd075b8b0863c5..25dcb4a112de1c7e030498a7167e97be22526055 100644 (file)
@@ -11,8 +11,9 @@
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, TokenKind};
 use rustc_ast::util::classify;
-use rustc_ast::AstLike;
-use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle};
+use rustc_ast::{
+    AstLike, AttrStyle, AttrVec, Attribute, LocalKind, MacCall, MacCallStmt, MacStmtStyle,
+};
 use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
 use rustc_ast::{StmtKind, DUMMY_NODE_ID};
 use rustc_errors::{Applicability, PResult};
@@ -292,8 +293,65 @@ fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
                 return Err(err);
             }
         };
+        let kind = match init {
+            None => LocalKind::Decl,
+            Some(init) => {
+                if self.eat_keyword(kw::Else) {
+                    let els = self.parse_block()?;
+                    self.check_let_else_init_bool_expr(&init);
+                    self.check_let_else_init_trailing_brace(&init);
+                    LocalKind::InitElse(init, els)
+                } else {
+                    LocalKind::Init(init)
+                }
+            }
+        };
         let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
-        Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
+        Ok(P(ast::Local { ty, pat, kind, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
+    }
+
+    fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
+        if let ast::ExprKind::Binary(op, ..) = init.kind {
+            if op.node.lazy() {
+                let suggs = vec![
+                    (init.span.shrink_to_lo(), "(".to_string()),
+                    (init.span.shrink_to_hi(), ")".to_string()),
+                ];
+                self.struct_span_err(
+                    init.span,
+                    &format!(
+                        "a `{}` expression cannot be directly assigned in `let...else`",
+                        op.node.to_string()
+                    ),
+                )
+                .multipart_suggestion(
+                    "wrap the expression in parenthesis",
+                    suggs,
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
+        if let Some(trailing) = classify::expr_trailing_brace(init) {
+            let err_span = trailing.span.with_lo(trailing.span.hi() - BytePos(1));
+            let suggs = vec![
+                (trailing.span.shrink_to_lo(), "(".to_string()),
+                (trailing.span.shrink_to_hi(), ")".to_string()),
+            ];
+            self.struct_span_err(
+                err_span,
+                "right curly brace `}` before `else` in a `let...else` statement not allowed",
+            )
+            .multipart_suggestion(
+                "try wrapping the expression in parenthesis",
+                suggs,
+                Applicability::MachineApplicable,
+            )
+            .emit();
+        }
     }
 
     /// Parses the RHS of a local variable declaration (e.g., `= 14;`).
@@ -493,21 +551,19 @@ pub fn parse_full_stmt(
                 }
             }
             StmtKind::Expr(_) | StmtKind::MacCall(_) => {}
-            StmtKind::Local(ref mut local) => {
-                if let Err(e) = self.expect_semi() {
-                    // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
-                    match &mut local.init {
-                        Some(ref mut expr) => {
+            StmtKind::Local(ref mut local) if let Err(e) = self.expect_semi() => {
+                // We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
+                match &mut local.kind {
+                    LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
                             self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
                             // We found `foo<bar, baz>`, have we fully recovered?
                             self.expect_semi()?;
                         }
-                        None => return Err(e),
-                    }
+                        LocalKind::Decl => return Err(e),
                 }
                 eat_semi = false;
             }
-            StmtKind::Empty | StmtKind::Item(_) | StmtKind::Semi(_) => eat_semi = false,
+            StmtKind::Empty | StmtKind::Item(_) | StmtKind::Local(_) | StmtKind::Semi(_) => eat_semi = false,
         }
 
         if eat_semi && self.eat(&token::Semi) {
@@ -518,7 +574,14 @@ pub fn parse_full_stmt(
     }
 
     pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
-        P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
+        P(Block {
+            stmts,
+            id: DUMMY_NODE_ID,
+            rules,
+            span,
+            tokens: None,
+            could_be_bare_literal: false,
+        })
     }
 
     pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
index 1fbf01b1b97d55ad5b3e300a2f1498d2fd7c3791..299fc916ac97fa7802b2f6a6865877dc8a0744e7 100644 (file)
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym};
 
-/// Any `?` or `?const` modifiers that appear at the start of a bound.
+/// Any `?` or `~const` modifiers that appear at the start of a bound.
 struct BoundModifiers {
     /// `?Trait`.
     maybe: Option<Span>,
 
-    /// `?const Trait`.
+    /// `~const Trait`.
     maybe_const: Option<Span>,
 }
 
@@ -609,6 +609,7 @@ fn can_begin_bound(&mut self) -> bool {
         || self.check_lifetime()
         || self.check(&token::Not) // Used for error reporting only.
         || self.check(&token::Question)
+        || self.check(&token::Tilde)
         || self.check_keyword(kw::For)
         || self.check(&token::OpenDelim(token::Paren))
     }
@@ -655,7 +656,7 @@ fn parse_generic_bound(&mut self) -> PResult<'a, Result<GenericBound, Span>> {
         let inner_lo = self.token.span;
         let is_negative = self.eat(&token::Not);
 
-        let modifiers = self.parse_ty_bound_modifiers();
+        let modifiers = self.parse_ty_bound_modifiers()?;
         let bound = if self.token.is_lifetime() {
             self.error_lt_bound_with_modifiers(modifiers);
             self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
@@ -690,7 +691,7 @@ fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
         if let Some(span) = modifiers.maybe_const {
             self.struct_span_err(
                 span,
-                "`?const` may only modify trait bounds, not lifetime bounds",
+                "`~const` may only modify trait bounds, not lifetime bounds",
             )
             .emit();
         }
@@ -721,34 +722,27 @@ fn recover_paren_lifetime(&mut self, lo: Span, inner_lo: Span) -> PResult<'a, ()
         Ok(())
     }
 
-    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `?const Trait`.
+    /// Parses the modifiers that may precede a trait in a bound, e.g. `?Trait` or `~const Trait`.
     ///
     /// If no modifiers are present, this does not consume any tokens.
     ///
     /// ```
-    /// TY_BOUND_MODIFIERS = "?" ["const" ["?"]]
+    /// TY_BOUND_MODIFIERS = ["~const"] ["?"]
     /// ```
-    fn parse_ty_bound_modifiers(&mut self) -> BoundModifiers {
-        if !self.eat(&token::Question) {
-            return BoundModifiers { maybe: None, maybe_const: None };
-        }
-
-        // `? ...`
-        let first_question = self.prev_token.span;
-        if !self.eat_keyword(kw::Const) {
-            return BoundModifiers { maybe: Some(first_question), maybe_const: None };
-        }
+    fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
+        let maybe_const = if self.eat(&token::Tilde) {
+            let tilde = self.prev_token.span;
+            self.expect_keyword(kw::Const)?;
+            let span = tilde.to(self.prev_token.span);
+            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+            Some(span)
+        } else {
+            None
+        };
 
-        // `?const ...`
-        let maybe_const = first_question.to(self.prev_token.span);
-        self.sess.gated_spans.gate(sym::const_trait_bound_opt_out, maybe_const);
-        if !self.eat(&token::Question) {
-            return BoundModifiers { maybe: None, maybe_const: Some(maybe_const) };
-        }
+        let maybe = if self.eat(&token::Question) { Some(self.prev_token.span) } else { None };
 
-        // `?const ? ...`
-        let second_question = self.prev_token.span;
-        BoundModifiers { maybe: Some(second_question), maybe_const: Some(maybe_const) }
+        Ok(BoundModifiers { maybe, maybe_const })
     }
 
     /// Parses a type bound according to:
@@ -757,7 +751,7 @@ fn parse_ty_bound_modifiers(&mut self) -> BoundModifiers {
     /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
     /// ```
     ///
-    /// For example, this grammar accepts `?const ?for<'a: 'b> m::Trait<'a>`.
+    /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
     fn parse_generic_ty_bound(
         &mut self,
         lo: Span,
index 21372725a6836b63fc2d45b62d25221f010e25ec..67695dc285092a555cc391e41bbe4e9e6eaedddc 100644 (file)
@@ -24,16 +24,15 @@ pub fn check_meta(sess: &ParseSess, attr: &Attribute) {
         Some((name, _, template, _)) if name != sym::rustc_dummy => {
             check_builtin_attribute(sess, attr, name, template)
         }
-        _ => {
-            if let MacArgs::Eq(..) = attr.get_normal_item().args {
-                // All key-value attributes are restricted to meta-item syntax.
-                parse_meta(sess, attr)
-                    .map_err(|mut err| {
-                        err.emit();
-                    })
-                    .ok();
-            }
+        _ if let MacArgs::Eq(..) = attr.get_normal_item().args => {
+            // All key-value attributes are restricted to meta-item syntax.
+            parse_meta(sess, attr)
+                .map_err(|mut err| {
+                    err.emit();
+                })
+                .ok();
         }
+        _ => {}
     }
 }
 
index d0ddad1c1a33477d12dd1442bc1280cc37ded517..fd438bdc9005ac5557c389bfa58ec7c9a5c860fe 100644 (file)
@@ -1331,6 +1331,36 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: &Span, target:
             Target::Field | Target::Arm | Target::MacroDef => {
                 self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle");
             }
+            // FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error
+            // The error should specify that the item that is wrong is specifically a *foreign* fn/static
+            // otherwise the error seems odd
+            Target::ForeignFn | Target::ForeignStatic => {
+                let foreign_item_kind = match target {
+                    Target::ForeignFn => "function",
+                    Target::ForeignStatic => "static",
+                    _ => unreachable!(),
+                };
+                self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                    lint.build(&format!(
+                        "`#[no_mangle]` has no effect on a foreign {}",
+                        foreign_item_kind
+                    ))
+                    .warn(
+                        "this was previously accepted by the compiler but is \
+                            being phased out; it will become a hard error in \
+                            a future release!",
+                    )
+                    .span_label(*span, format!("foreign {}", foreign_item_kind))
+                    .note("symbol names in extern blocks are not mangled")
+                    .span_suggestion(
+                        attr.span,
+                        "remove this attribute",
+                        String::new(),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
+                });
+            }
             _ => {
                 // FIXME: #[no_mangle] was previously allowed on non-functions/statics and some
                 // crates used this, so only emit a warning.
@@ -1723,6 +1753,16 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     }
 
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
+        // Historically we've run more checks on non-exported than exported macros,
+        // so this lets us continue to run them while maintaining backwards compatibility.
+        // In the long run, the checks should be harmonized.
+        if let ItemKind::Macro(ref macro_def) = item.kind {
+            let def_id = item.def_id.to_def_id();
+            if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
+                check_non_exported_macro_for_invalid_attrs(self.tcx, item);
+            }
+        }
+
         let target = Target::from_item(item);
         self.check_attributes(item.hir_id(), &item.span, target, Some(ItemLike::Item(item)));
         intravisit::walk_item(self, item)
@@ -1795,11 +1835,6 @@ fn visit_variant(
         intravisit::walk_variant(self, variant, generics, item_id)
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef<'tcx>) {
-        self.check_attributes(macro_def.hir_id(), &macro_def.span, Target::MacroDef, None);
-        intravisit::walk_macro_def(self, macro_def);
-    }
-
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
         self.check_attributes(param.hir_id, &param.span, Target::Param, None);
 
@@ -1848,7 +1883,9 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
     }
 }
 
-fn check_invalid_macro_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
+fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
+    let attrs = tcx.hir().attrs(item.hir_id());
+
     for attr in attrs {
         if attr.has_name(sym::inline) {
             struct_span_err!(
@@ -1869,8 +1906,6 @@ fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     if module_def_id.is_top_level_module() {
         check_attr_visitor.check_attributes(CRATE_HIR_ID, &DUMMY_SP, Target::Mod, None);
         check_invalid_crate_level_attr(tcx, tcx.hir().krate_attrs());
-        tcx.hir().visit_exported_macros_in_krate(check_attr_visitor);
-        check_invalid_macro_level_attr(tcx, tcx.hir().krate().non_exported_macro_attrs);
     }
 }
 
index ae65222f3f22fc450d959293fa9a4152799382dc..25ad00aaf1f753caa8f98f37224d898d5e1528ee 100644 (file)
@@ -775,5 +775,5 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     let krate = tcx.hir().krate();
     let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor { tcx, live_symbols };
-    intravisit::walk_crate(&mut visitor, krate);
+    tcx.hir().walk_toplevel_module(&mut visitor);
 }
index e43abda713351c6042a95a06eeb88713defaf27d..3f12a744be0e819cc69ad20f2813ce0fbfd18d21 100644 (file)
@@ -107,10 +107,6 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> FxHashMap<Symbol
     // Collect diagnostic items in this crate.
     tcx.hir().krate().visit_all_item_likes(&mut collector);
 
-    for m in tcx.hir().krate().exported_macros() {
-        collector.observe_item(m.def_id);
-    }
-
     collector.items
 }
 
index 944a3097a61c33ee476631a3aa956d3ab55018be..18f61c6e1c1a787df5b6733e881d0db950c4f3f2 100644 (file)
 pub fn check_crate(tcx: TyCtxt<'_>) {
     tcx.dep_graph.assert_ignored();
 
+    if tcx.sess.opts.debugging_opts.hir_stats {
+        crate::hir_stats::print_hir_stats(tcx);
+    }
+
     let errors = Lock::new(Vec::new());
     let hir_map = tcx.hir();
 
index 2bed8cadeb95dde915d1306c74905a335683c8a4..d665c12f762c5baa49a0fb6974c847191d196f34 100644 (file)
@@ -9,6 +9,7 @@
 use rustc_hir::intravisit as hir_visit;
 use rustc_hir::HirId;
 use rustc_middle::hir::map::Map;
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::util::common::to_readable_str;
 use rustc_span::Span;
 
@@ -25,18 +26,19 @@ struct NodeData {
 }
 
 struct StatCollector<'k> {
-    krate: Option<&'k hir::Crate<'k>>,
+    krate: Option<Map<'k>>,
     data: FxHashMap<&'static str, NodeData>,
     seen: FxHashSet<Id>,
 }
 
-pub fn print_hir_stats(krate: &hir::Crate<'_>) {
+pub fn print_hir_stats(tcx: TyCtxt<'_>) {
     let mut collector = StatCollector {
-        krate: Some(krate),
+        krate: Some(tcx.hir()),
         data: FxHashMap::default(),
         seen: FxHashSet::default(),
     };
-    hir_visit::walk_crate(&mut collector, krate);
+    tcx.hir().walk_toplevel_module(&mut collector);
+    tcx.hir().walk_attributes(&mut collector);
     collector.print("HIR STATS");
 }
 
@@ -244,11 +246,6 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding<'v>) {
     fn visit_attribute(&mut self, _: hir::HirId, attr: &'v ast::Attribute) {
         self.record("Attribute", Id::Attr(attr.id), attr);
     }
-
-    fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef<'v>) {
-        self.record("MacroDef", Id::Node(macro_def.hir_id()), macro_def);
-        hir_visit::walk_macro_def(self, macro_def)
-    }
 }
 
 impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
index 62f9bcfdc47299bc2a1a59ec9304b3cd361ed634..77ff8dc5b4aee26e6dc6208341277637b231e553 100644 (file)
@@ -18,7 +18,7 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::lang_items::{extract, ITEM_REFS};
+use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
 use rustc_hir::{HirId, LangItem, LanguageItems, Target};
 use rustc_span::Span;
 
@@ -183,97 +183,39 @@ fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
     }
 
     // Like collect_item() above, but also checks whether the lang item is declared
-    // with the right number of generic arguments if it is a trait.
+    // with the right number of generic arguments.
     fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
         let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
         let lang_item = LangItem::from_u32(item_index as u32).unwrap();
         let name = lang_item.name();
 
-        self.collect_item(item_index, item_def_id);
-
         // Now check whether the lang_item has the expected number of generic
-        // arguments if it is a trait. Generally speaking, binary and indexing
-        // operations have one (for the RHS/index), unary operations have none,
-        // and the rest also have none except for the closure traits (one for
-        // the argument list), generators (one for the resume argument),
-        // ordering/equality relations (one for the RHS), and various conversion
-        // traits.
-
-        let expected_num = match lang_item {
-            // Binary operations
-            LangItem::Add
-            | LangItem::Sub
-            | LangItem::Mul
-            | LangItem::Div
-            | LangItem::Rem
-            | LangItem::BitXor
-            | LangItem::BitAnd
-            | LangItem::BitOr
-            | LangItem::Shl
-            | LangItem::Shr
-            | LangItem::AddAssign
-            | LangItem::SubAssign
-            | LangItem::MulAssign
-            | LangItem::DivAssign
-            | LangItem::RemAssign
-            | LangItem::BitXorAssign
-            | LangItem::BitAndAssign
-            | LangItem::BitOrAssign
-            | LangItem::ShlAssign
-            | LangItem::ShrAssign
-            | LangItem::Index
-            | LangItem::IndexMut
-
-            // Miscellaneous
-            | LangItem::Unsize
-            | LangItem::CoerceUnsized
-            | LangItem::DispatchFromDyn
-            | LangItem::Fn
-            | LangItem::FnMut
-            | LangItem::FnOnce
-            | LangItem::Generator
-            | LangItem::PartialEq
-            | LangItem::PartialOrd
-                => Some(1),
-
-            // Unary operations
-            LangItem::Neg
-            | LangItem::Not
-
-            // Miscellaneous
-            | LangItem::Deref
-            | LangItem::DerefMut
-            | LangItem::Sized
-            | LangItem::StructuralPeq
-            | LangItem::StructuralTeq
-            | LangItem::Copy
-            | LangItem::Clone
-            | LangItem::Sync
-            | LangItem::DiscriminantKind
-            | LangItem::PointeeTrait
-            | LangItem::Freeze
-            | LangItem::Drop
-            | LangItem::Receiver
-            | LangItem::Future
-            | LangItem::Unpin
-            | LangItem::Termination
-            | LangItem::Try
-                => Some(0),
+        // arguments. Generally speaking, binary and indexing operations have
+        // one (for the RHS/index), unary operations have none, the closure
+        // traits have one for the argument list, generators have one for the
+        // resume argument, and ordering/equality relations have one for the RHS
+        // Some other types like Box and various functions like drop_in_place
+        // have minimum requirements.
 
-            // Not a trait
-            _ => None,
-        };
+        if let hir::Node::Item(hir::Item { kind, span: item_span, .. }) = self.tcx.hir().get(hir_id)
+        {
+            let (actual_num, generics_span) = match kind.generics() {
+                Some(generics) => (generics.params.len(), generics.span),
+                None => (0, *item_span),
+            };
 
-        if let Some(expected_num) = expected_num {
-            let (actual_num, generics_span) = match self.tcx.hir().get(hir_id) {
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, ..),
-                    ..
-                }) => (generics.params.len(), generics.span),
-                _ => bug!("op/index/deref lang item target is not a trait: {:?}", lang_item),
+            let required = match lang_item.required_generics() {
+                GenericRequirement::Exact(num) if num != actual_num => {
+                    Some((format!("{}", num), pluralize!(num)))
+                }
+                GenericRequirement::Minimum(num) if actual_num < num => {
+                    Some((format!("at least {}", num), pluralize!(num)))
+                }
+                // If the number matches, or there is no requirement, handle it normally
+                _ => None,
             };
 
-            if expected_num != actual_num {
+            if let Some((range_str, pluralized)) = required {
                 // We are issuing E0718 "incorrect target" here, because while the
                 // item kind of the target is correct, the target is still wrong
                 // because of the wrong number of generic arguments.
@@ -281,23 +223,29 @@ fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span
                     self.tcx.sess,
                     span,
                     E0718,
-                    "`{}` language item must be applied to a trait with {} generic argument{}",
+                    "`{}` language item must be applied to a {} with {} generic argument{}",
                     name,
-                    expected_num,
-                    pluralize!(expected_num)
+                    kind.descr(),
+                    range_str,
+                    pluralized,
                 )
                 .span_label(
                     generics_span,
                     format!(
-                        "this trait has {} generic argument{}, not {}",
+                        "this {} has {} generic argument{}",
+                        kind.descr(),
                         actual_num,
                         pluralize!(actual_num),
-                        expected_num
                     ),
                 )
                 .emit();
+
+                // return early to not collect the lang item
+                return;
             }
         }
+
+        self.collect_item(item_index, item_def_id);
     }
 }
 
index 43a3a3062e77b053f02ba8117cf5f8315218d284..aa78fcfb4b373cc42066634ba885784ac7acb44b 100644 (file)
@@ -3,10 +3,11 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::ItemKind;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::sym;
-use rustc_target::abi::{HasDataLayout, LayoutOf, TargetDataLayout};
+use rustc_span::Span;
+use rustc_target::abi::{HasDataLayout, TargetDataLayout};
 
 pub fn test_layout(tcx: TyCtxt<'_>) {
     if tcx.features().rustc_attrs {
@@ -113,12 +114,16 @@ struct UnwrapLayoutCx<'tcx> {
     param_env: ParamEnv<'tcx>,
 }
 
-impl LayoutOf for UnwrapLayoutCx<'tcx> {
-    type Ty = Ty<'tcx>;
-    type TyAndLayout = TyAndLayout<'tcx>;
+impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
+    type LayoutOfResult = TyAndLayout<'tcx>;
 
-    fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx.layout_of(self.param_env.and(ty)).unwrap()
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        span_bug!(
+            span,
+            "`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`",
+            ty,
+            err
+        );
     }
 }
 
index 605b52f18913f2c22df23a556965c6cb47af3c34..ff8bd37238d6bc7db187fb58509da637e6919df1 100644 (file)
@@ -6,7 +6,7 @@
 
 use rustc_ast::{Attribute, MetaItem, MetaItemKind};
 use rustc_errors::struct_span_err;
-use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::lib_features::LibFeatures;
 use rustc_middle::ty::query::Providers;
@@ -126,11 +126,7 @@ fn visit_attribute(&mut self, _: rustc_hir::HirId, attr: &'tcx Attribute) {
 
 fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures {
     let mut collector = LibFeatureCollector::new(tcx);
-    let krate = tcx.hir().krate();
-    for attr in krate.non_exported_macro_attrs {
-        collector.visit_attribute(rustc_hir::CRATE_HIR_ID, attr);
-    }
-    intravisit::walk_crate(&mut collector, krate);
+    tcx.hir().walk_attributes(&mut collector);
     collector.lib_features
 }
 
index 36d1a6c104421c6ca7d5c2ac6d91e55820bdc66d..ab9bfea96943f3eafe4505a4c7660d61bdfdf205 100644 (file)
@@ -337,8 +337,8 @@ fn visit_body(&mut self, body: &'tcx hir::Body<'tcx>) {
             return;
         }
 
-        if let Some(captures) = maps.tcx.typeck(local_def_id).closure_min_captures.get(&def_id) {
-            for &var_hir_id in captures.keys() {
+        if let Some(upvars) = maps.tcx.upvars_mentioned(def_id) {
+            for &var_hir_id in upvars.keys() {
                 let var_name = maps.tcx.hir().name(var_hir_id);
                 maps.add_variable(Upvar(var_hir_id, var_name));
             }
@@ -405,21 +405,14 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
                 // breaks or continues)
                 self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
 
-                // Make a live_node for each captured variable, with the span
+                // Make a live_node for each mentioned variable, with the span
                 // being the location that the variable is used.  This results
                 // in better error messages than just pointing at the closure
                 // construction site.
                 let mut call_caps = Vec::new();
                 let closure_def_id = self.tcx.hir().local_def_id(expr.hir_id);
-                if let Some(captures) = self
-                    .tcx
-                    .typeck(closure_def_id)
-                    .closure_min_captures
-                    .get(&closure_def_id.to_def_id())
-                {
-                    // If closure_min_captures is Some, upvars_mentioned must also be Some
-                    let upvars = self.tcx.upvars_mentioned(closure_def_id).unwrap();
-                    call_caps.extend(captures.keys().map(|var_id| {
+                if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
+                    call_caps.extend(upvars.keys().map(|var_id| {
                         let upvar = upvars[var_id];
                         let upvar_ln = self.add_live_node(UpvarNode(upvar.span));
                         CaptureInfo { ln: upvar_ln, var_hid: *var_id }
@@ -435,7 +428,10 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             }
 
             // live nodes required for interesting control flow:
-            hir::ExprKind::If(..) | hir::ExprKind::Match(..) | hir::ExprKind::Loop(..) => {
+            hir::ExprKind::If(..)
+            | hir::ExprKind::Match(..)
+            | hir::ExprKind::Loop(..)
+            | hir::ExprKind::Yield(..) => {
                 self.add_live_node_for_node(expr.hir_id, ExprNode(expr.span, expr.hir_id));
                 intravisit::walk_expr(self, expr);
             }
@@ -469,7 +465,6 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
             | hir::ExprKind::InlineAsm(..)
             | hir::ExprKind::LlvmInlineAsm(..)
             | hir::ExprKind::Box(..)
-            | hir::ExprKind::Yield(..)
             | hir::ExprKind::Type(..)
             | hir::ExprKind::Err
             | hir::ExprKind::Path(hir::QPath::TypeRelative(..))
@@ -494,7 +489,6 @@ struct Liveness<'a, 'tcx> {
     ir: &'a mut IrMaps<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
     closure_min_captures: Option<&'tcx RootVariableMinCaptureList<'tcx>>,
     successors: IndexVec<LiveNode, Option<LiveNode>>,
     rwu_table: rwu_table::RWUTable,
@@ -518,7 +512,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> {
         let typeck_results = ir.tcx.typeck(body_owner);
         let param_env = ir.tcx.param_env(body_owner);
-        let upvars = ir.tcx.upvars_mentioned(body_owner);
         let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner.to_def_id());
         let closure_ln = ir.add_live_node(ClosureNode);
         let exit_ln = ir.add_live_node(ExitNode);
@@ -530,7 +523,6 @@ fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> {
             ir,
             typeck_results,
             param_env,
-            upvars,
             closure_min_captures,
             successors: IndexVec::from_elem_n(None, num_live_nodes),
             rwu_table: rwu_table::RWUTable::new(num_live_nodes, num_vars),
@@ -866,6 +858,13 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
             // at the label ident
             hir::ExprKind::Loop(ref blk, ..) => self.propagate_through_loop(expr, &blk, succ),
 
+            hir::ExprKind::Yield(ref e, ..) => {
+                let yield_ln = self.live_node(expr.hir_id, expr.span);
+                self.init_from_succ(yield_ln, succ);
+                self.merge_from_succ(yield_ln, self.exit_ln);
+                self.propagate_through_expr(e, yield_ln)
+            }
+
             hir::ExprKind::If(ref cond, ref then, ref else_opt) => {
                 //
                 //     (cond)
@@ -1025,7 +1024,6 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
             | hir::ExprKind::Type(ref e, _)
             | hir::ExprKind::DropTemps(ref e)
             | hir::ExprKind::Unary(_, ref e)
-            | hir::ExprKind::Yield(ref e, _)
             | hir::ExprKind::Repeat(ref e, _) => self.propagate_through_expr(&e, succ),
 
             hir::ExprKind::InlineAsm(ref asm) => {
@@ -1215,21 +1213,7 @@ fn access_path(
         acc: u32,
     ) -> LiveNode {
         match path.res {
-            Res::Local(hid) => {
-                let in_upvars = self.upvars.map_or(false, |u| u.contains_key(&hid));
-                let in_captures = self.closure_min_captures.map_or(false, |c| c.contains_key(&hid));
-
-                match (in_upvars, in_captures) {
-                    (false, _) | (true, true) => self.access_var(hir_id, hid, succ, acc, path.span),
-                    (true, false) => {
-                        // This case is possible when with RFC-2229, a wild pattern
-                        // is used within a closure.
-                        // eg: `let _ = x`. The closure doesn't capture x here,
-                        // even though it's mentioned in the closure.
-                        succ
-                    }
-                }
-            }
+            Res::Local(hid) => self.access_var(hir_id, hid, succ, acc, path.span),
             _ => succ,
         }
     }
index 5ca098c22878b8d52934b52ae13df55533973499..23f43233b79ca5906d9628acacc25c46faea16ce 100644 (file)
@@ -263,6 +263,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
                     | hir::ItemKind::Use(..)
                     | hir::ItemKind::OpaqueTy(..)
                     | hir::ItemKind::TyAlias(..)
+                    | hir::ItemKind::Macro(..)
                     | hir::ItemKind::Mod(..)
                     | hir::ItemKind::ForeignMod { .. }
                     | hir::ItemKind::Impl { .. }
@@ -309,8 +310,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
             | Node::Ctor(..)
             | Node::Field(_)
             | Node::Ty(_)
-            | Node::Crate(_)
-            | Node::MacroDef(_) => {}
+            | Node::Crate(_) => {}
             _ => {
                 bug!(
                     "found unexpected node kind in worklist: {} ({:?})",
index 7403e51c7341b84974f54db455dbc1dd5a1bf264..08702cad41c8b92b5e0a80676f16dd22d6e5b6c0 100644 (file)
@@ -391,21 +391,22 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
         }
 
         hir::ExprKind::If(ref cond, ref then, Some(ref otherwise)) => {
-            // FIXME(matthewjasper): ideally the scope we use here would only
-            // contain the condition and then expression. This works, but
-            // can result in some extra drop flags.
+            let expr_cx = visitor.cx;
+            visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
-            visitor.cx.var_parent = prev_cx.var_parent;
             visitor.visit_expr(then);
+            visitor.cx = expr_cx;
             visitor.visit_expr(otherwise);
         }
 
         hir::ExprKind::If(ref cond, ref then, None) => {
+            let expr_cx = visitor.cx;
+            visitor.enter_scope(Scope { id: then.hir_id.local_id, data: ScopeData::IfThen });
             visitor.cx.var_parent = visitor.cx.parent;
             visitor.visit_expr(cond);
-            visitor.cx.var_parent = prev_cx.var_parent;
             visitor.visit_expr(then);
+            visitor.cx = expr_cx;
         }
 
         _ => intravisit::walk_expr(visitor, expr),
index b64dcb0bbf03b00ed6dea5cffdc85f40838671e4..b7e43b7785da602a170632beddb3ad53f0083155 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant};
 use rustc_middle::hir::map::Map;
@@ -538,19 +539,6 @@ fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         );
     }
 
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        self.annotate(
-            md.def_id,
-            md.span,
-            None,
-            AnnotationKind::Required,
-            InheritDeprecation::Yes,
-            InheritConstStability::No,
-            InheritStability::No,
-            |_| {},
-        );
-    }
-
     fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
         let kind = match &p.kind {
             // Allow stability attributes on default generic arguments.
@@ -662,11 +650,6 @@ fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
         self.check_missing_stability(i.def_id, i.span);
         intravisit::walk_foreign_item(self, i);
     }
-
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        self.check_missing_stability(md.def_id, md.span);
-    }
-
     // Note that we don't need to `check_missing_stability` for default generic parameters,
     // as we assume that any default generic parameters without attributes are automatically
     // stable (assuming they have not inherited instability from their parent).
@@ -696,7 +679,6 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
         .collect();
 
     {
-        let krate = tcx.hir().krate();
         let mut annotator = Annotator {
             tcx,
             index: &mut index,
@@ -729,13 +711,13 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
 
         annotator.annotate(
             CRATE_DEF_ID,
-            krate.module().inner,
+            tcx.hir().span(CRATE_HIR_ID),
             None,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
             InheritStability::No,
-            |v| intravisit::walk_crate(v, krate),
+            |v| tcx.hir().walk_toplevel_module(v),
         );
     }
     index
@@ -926,8 +908,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir().krate();
         let mut missing = MissingStabilityAnnotations { tcx, access_levels };
-        missing.check_missing_stability(CRATE_DEF_ID, krate.module().inner);
-        intravisit::walk_crate(&mut missing, krate);
+        missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
+        tcx.hir().walk_toplevel_module(&mut missing);
         krate.visit_all_item_likes(&mut missing.as_deep_visitor());
     }
 
index 85a53b1bde2249670c8b998abf70291bce116335..6ac2915c3452688b40b1d98ac57f040b10a8f486 100644 (file)
@@ -5,6 +5,7 @@ edition = "2018"
 
 [dependencies]
 rustc_middle = { path = "../rustc_middle" }
+rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_hir = { path = "../rustc_hir" }
index d84175724cc3238a63179e305d3f28ce87319d90..35e25e52dc5f9f1e2fc12b492055eff4eeb9dbd3 100644 (file)
@@ -6,6 +6,7 @@
 #![feature(associated_type_defaults)]
 #![recursion_limit = "256"]
 
+use rustc_ast::MacroDef;
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
@@ -26,7 +27,7 @@
 use rustc_middle::ty::{self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable};
 use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::traits::const_evaluatable::{self, AbstractConst};
 
@@ -134,11 +135,11 @@ fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<V::
                 ty.visit_with(self)
             }
             ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
-            ty::PredicateKind::ConstEvaluatable(defs, substs)
-                if self.def_id_visitor.tcx().features().const_evaluatable_checked =>
+            ty::PredicateKind::ConstEvaluatable(uv)
+                if self.def_id_visitor.tcx().features().generic_const_exprs =>
             {
                 let tcx = self.def_id_visitor.tcx();
-                if let Ok(Some(ct)) = AbstractConst::new(tcx, defs, substs) {
+                if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
                     self.visit_abstract_const_expr(tcx, ct)?;
                 }
                 ControlFlow::CONTINUE
@@ -179,6 +180,10 @@ impl<'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'tcx, V>
 {
     type BreakTy = V::BreakTy;
 
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.def_id_visitor.tcx())
+    }
+
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
         // InternalSubsts are not visited here because they are visited below in `super_visit_with`.
@@ -458,6 +463,43 @@ fn reach(
         }
     }
 
+    // We have to make sure that the items that macros might reference
+    // are reachable, since they might be exported transitively.
+    fn update_reachability_from_macro(&mut self, local_def_id: LocalDefId, md: &MacroDef) {
+        // Non-opaque macros cannot make other items more accessible than they already are.
+
+        let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id);
+        let attrs = self.tcx.hir().attrs(hir_id);
+        if attr::find_transparency(&attrs, md.macro_rules).0 != Transparency::Opaque {
+            return;
+        }
+
+        let item_def_id = local_def_id.to_def_id();
+        let macro_module_def_id =
+            ty::DefIdTree::parent(self.tcx, item_def_id).unwrap().expect_local();
+        if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) {
+            // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
+            return;
+        }
+
+        if self.get(local_def_id).is_none() {
+            return;
+        }
+
+        // Since we are starting from an externally visible module,
+        // all the parents in the loop below are also guaranteed to be modules.
+        let mut module_def_id = macro_module_def_id;
+        loop {
+            let changed_reachability =
+                self.update_macro_reachable(module_def_id, macro_module_def_id);
+            if changed_reachability || module_def_id == CRATE_DEF_ID {
+                break;
+            }
+            module_def_id =
+                ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local();
+        }
+    }
+
     /// Updates the item as being reachable through a macro defined in the given
     /// module. Returns `true` if the level has changed.
     fn update_macro_reachable(
@@ -507,16 +549,26 @@ fn update_macro_reachable_def(
         }
         match def_kind {
             // No type privacy, so can be directly marked as reachable.
-            DefKind::Const
-            | DefKind::Macro(_)
-            | DefKind::Static
-            | DefKind::TraitAlias
-            | DefKind::TyAlias => {
+            DefKind::Const | DefKind::Static | DefKind::TraitAlias | DefKind::TyAlias => {
                 if vis.is_accessible_from(module.to_def_id(), self.tcx) {
                     self.update(def_id, level);
                 }
             }
 
+            // Hygine isn't really implemented for `macro_rules!` macros at the
+            // moment. Accordingly, marking them as reachable is unwise. `macro` macros
+            // have normal  hygine, so we can treat them like other items without type
+            // privacy and mark them reachable.
+            DefKind::Macro(_) => {
+                let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
+                let item = self.tcx.hir().expect_item(hir_id);
+                if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind {
+                    if vis.is_accessible_from(module.to_def_id(), self.tcx) {
+                        self.update(def_id, level);
+                    }
+                }
+            }
+
             // We can't use a module name as the final segment of a path, except
             // in use statements. Since re-export checking doesn't consider
             // hygiene these don't need to be marked reachable. The contents of
@@ -640,6 +692,12 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             hir::ItemKind::Impl { .. } => {
                 Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels)
             }
+            // Only exported `macro_rules!` items are public, but they always are.
+            hir::ItemKind::Macro(MacroDef { macro_rules: true, .. }) => {
+                let def_id = item.def_id.to_def_id();
+                let is_macro_export = self.tcx.has_attr(def_id, sym::macro_export);
+                if is_macro_export { Some(AccessLevel::Public) } else { None }
+            }
             // Foreign modules inherit level from parents.
             hir::ItemKind::ForeignMod { .. } => self.prev_level,
             // Other `pub` items inherit levels from parents.
@@ -648,6 +706,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             | hir::ItemKind::ExternCrate(..)
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::Fn(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Struct(..)
@@ -704,6 +763,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     }
                 }
             }
+            hir::ItemKind::Macro(ref macro_def) => {
+                self.update_reachability_from_macro(item.def_id, macro_def);
+            }
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
                     if foreign_item.vis.node.is_pub() {
@@ -711,6 +773,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     }
                 }
             }
+
             hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Use(..)
             | hir::ItemKind::Static(..)
@@ -726,7 +789,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         // Mark all items in interfaces of reachable items as reachable.
         match item.kind {
             // The interface is empty.
-            hir::ItemKind::ExternCrate(..) => {}
+            hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
             // All nested items are checked by `visit_item`.
             hir::ItemKind::Mod(..) => {}
             // Re-exports are handled in `visit_mod`. However, in order to avoid looping over
@@ -881,45 +944,6 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _sp: Span, id: hir::HirId) {
 
         intravisit::walk_mod(self, m, id);
     }
-
-    fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
-        // Non-opaque macros cannot make other items more accessible than they already are.
-        let attrs = self.tcx.hir().attrs(md.hir_id());
-        if attr::find_transparency(&attrs, md.ast.macro_rules).0 != Transparency::Opaque {
-            // `#[macro_export]`-ed `macro_rules!` are `Public` since they
-            // ignore their containing path to always appear at the crate root.
-            if md.ast.macro_rules {
-                self.update(md.def_id, Some(AccessLevel::Public));
-            }
-            return;
-        }
-
-        let macro_module_def_id =
-            ty::DefIdTree::parent(self.tcx, md.def_id.to_def_id()).unwrap().expect_local();
-        if self.tcx.hir().opt_def_kind(macro_module_def_id) != Some(DefKind::Mod) {
-            // The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
-            return;
-        }
-
-        let level = if md.vis.node.is_pub() { self.get(macro_module_def_id) } else { None };
-        let new_level = self.update(md.def_id, level);
-        if new_level.is_none() {
-            return;
-        }
-
-        // Since we are starting from an externally visible module,
-        // all the parents in the loop below are also guaranteed to be modules.
-        let mut module_def_id = macro_module_def_id;
-        loop {
-            let changed_reachability =
-                self.update_macro_reachable(module_def_id, macro_module_def_id);
-            if changed_reachability || module_def_id == CRATE_DEF_ID {
-                break;
-            }
-            module_def_id =
-                ty::DefIdTree::parent(self.tcx, module_def_id.to_def_id()).unwrap().expect_local();
-        }
-    }
 }
 
 impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
@@ -1785,7 +1809,7 @@ fn generics(&mut self) -> &mut Self {
                         self.visit(self.tcx.type_of(param.def_id));
                     }
                 }
-                // FIXME(const_evaluatable_checked): May want to look inside const here
+                // FIXME(generic_const_exprs): May want to look inside const here
                 GenericParamDefKind::Const { .. } => {
                     self.visit(self.tcx.type_of(param.def_id));
                 }
@@ -1977,7 +2001,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             // Checked in resolve.
             hir::ItemKind::Use(..) => {}
             // No subitems.
-            hir::ItemKind::GlobalAsm(..) => {}
+            hir::ItemKind::Macro(..) | hir::ItemKind::GlobalAsm(..) => {}
             // Subitems of these items have inherited publicity.
             hir::ItemKind::Const(..)
             | hir::ItemKind::Static(..)
@@ -2145,7 +2169,7 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
         changed: false,
     };
     loop {
-        intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+        tcx.hir().walk_toplevel_module(&mut visitor);
         if visitor.changed {
             visitor.changed = false;
         } else {
@@ -2168,11 +2192,11 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
         in_variant: false,
         old_error_set: Default::default(),
     };
-    intravisit::walk_crate(&mut visitor, krate);
+    tcx.hir().walk_toplevel_module(&mut visitor);
 
     let has_pub_restricted = {
         let mut pub_restricted_visitor = PubRestrictedVisitor { tcx, has_pub_restricted: false };
-        intravisit::walk_crate(&mut pub_restricted_visitor, krate);
+        tcx.hir().walk_toplevel_module(&mut pub_restricted_visitor);
         pub_restricted_visitor.has_pub_restricted
     };
 
index 38ab26d66ac6aefe4625f7a8954df9524714a42a..42e8b4023cfad489c219d106031baaf804cfdc79 100644 (file)
@@ -20,6 +20,12 @@ pub trait Key {
     /// In the event that a cycle occurs, if no explicit span has been
     /// given for a query with key `self`, what span should we use?
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span;
+
+    /// If the key is a [`DefId`] or `DefId`--equivalent, return that `DefId`.
+    /// Otherwise, return `None`.
+    fn key_as_def_id(&self) -> Option<DefId> {
+        None
+    }
 }
 
 impl Key for () {
@@ -95,6 +101,9 @@ fn query_crate_is_local(&self) -> bool {
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         self.to_def_id().default_span(tcx)
     }
+    fn key_as_def_id(&self) -> Option<DefId> {
+        Some(self.to_def_id())
+    }
 }
 
 impl Key for DefId {
@@ -105,6 +114,10 @@ fn query_crate_is_local(&self) -> bool {
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(*self)
     }
+    #[inline(always)]
+    fn key_as_def_id(&self) -> Option<DefId> {
+        Some(*self)
+    }
 }
 
 impl Key for ty::WithOptConstParam<LocalDefId> {
@@ -165,6 +178,10 @@ fn query_crate_is_local(&self) -> bool {
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
         tcx.def_span(self.0)
     }
+    #[inline(always)]
+    fn key_as_def_id(&self) -> Option<DefId> {
+        Some(self.0)
+    }
 }
 
 impl Key for (DefId, LocalDefId, Ident) {
@@ -217,18 +234,13 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
     }
 }
 
-impl<'tcx> Key
-    for (
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
-    )
-{
+impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
-        (self.0).0.did.krate == LOCAL_CRATE
+        (self.0).def.did.krate == LOCAL_CRATE
     }
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
-        (self.0).0.did.default_span(tcx)
+        (self.0).def.did.default_span(tcx)
     }
 }
 
@@ -282,6 +294,16 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
     }
 }
 
+impl<'tcx> Key for ty::PolyExistentialTraitRef<'tcx> {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        self.def_id().krate == LOCAL_CRATE
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        tcx.def_span(self.def_id())
+    }
+}
+
 impl<'tcx> Key for (ty::PolyTraitRef<'tcx>, ty::PolyTraitRef<'tcx>) {
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
index 5022bf265328a9a3d16d4f256c991f89dcba2a29..bb0e65111596cb290ec8c73b9a045a68f0062821 100644 (file)
@@ -51,6 +51,8 @@
 mod profiling_support;
 pub use self::profiling_support::alloc_self_profile_query_strings;
 
+mod util;
+
 rustc_query_append! { [define_queries!][<'tcx>] }
 
 impl<'tcx> Queries<'tcx> {
index 5774d021373bb16ebb7fb5907c24f93d2dec9790..90a6ba474b405acd1b2c8fcbeedf11b4cc28bfb7 100644 (file)
@@ -337,6 +337,13 @@ pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryS
                 } else {
                     Some(key.default_span(*tcx))
                 };
+                let def_id = key.key_as_def_id();
+                let def_kind = def_id
+                    .and_then(|def_id| def_id.as_local())
+                    // Use `tcx.hir().opt_def_kind()` to reduce the chance of
+                    // accidentally triggering an infinite query loop.
+                    .and_then(|def_id| tcx.hir().opt_def_kind(def_id))
+                    .map(|def_kind| $crate::util::def_kind_to_simple_def_kind(def_kind));
                 let hash = || {
                     let mut hcx = tcx.create_stable_hashing_context();
                     let mut hasher = StableHasher::new();
@@ -345,7 +352,7 @@ pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryS
                     hasher.finish::<u64>()
                 };
 
-                QueryStackFrame::new(name, description, span, hash)
+                QueryStackFrame::new(name, description, span, def_kind, hash)
             })*
         }
 
diff --git a/compiler/rustc_query_impl/src/util.rs b/compiler/rustc_query_impl/src/util.rs
new file mode 100644 (file)
index 0000000..517c107
--- /dev/null
@@ -0,0 +1,18 @@
+use rustc_hir::def::DefKind;
+use rustc_query_system::query::SimpleDefKind;
+
+/// Convert a [`DefKind`] to a [`SimpleDefKind`].
+///
+/// *See [`SimpleDefKind`]'s docs for more information.*
+pub(crate) fn def_kind_to_simple_def_kind(def_kind: DefKind) -> SimpleDefKind {
+    match def_kind {
+        DefKind::Struct => SimpleDefKind::Struct,
+        DefKind::Enum => SimpleDefKind::Enum,
+        DefKind::Union => SimpleDefKind::Union,
+        DefKind::Trait => SimpleDefKind::Trait,
+        DefKind::TyAlias => SimpleDefKind::TyAlias,
+        DefKind::TraitAlias => SimpleDefKind::TraitAlias,
+
+        _ => SimpleDefKind::Other,
+    }
+}
index a967670280ff2ec8990ad27481d0bef354a164ec..c3fdf4fc228511b0ebc767267f052461f681196a 100644 (file)
@@ -1,6 +1,6 @@
 use crate::dep_graph::DepContext;
 use crate::query::plumbing::CycleError;
-use crate::query::{QueryContext, QueryStackFrame};
+use crate::query::{QueryContext, QueryStackFrame, SimpleDefKind};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level};
@@ -61,7 +61,7 @@ pub fn new(job: QueryShardJobId, shard: usize, kind: D) -> Self {
     }
 
     fn query(self, map: &QueryMap<D>) -> QueryStackFrame {
-        map.get(&self).unwrap().info.query.clone()
+        map.get(&self).unwrap().query.clone()
     }
 
     #[cfg(parallel_compiler)]
@@ -81,7 +81,7 @@ fn latch<'a>(self, map: &'a QueryMap<D>) -> Option<&'a QueryLatch<D>> {
 }
 
 pub struct QueryJobInfo<D> {
-    pub info: QueryInfo,
+    pub query: QueryStackFrame,
     pub job: QueryJob<D>,
 }
 
@@ -155,7 +155,7 @@ pub(super) fn find_cycle_in_stack(
 
         while let Some(job) = current_job {
             let info = query_map.get(&job).unwrap();
-            cycle.push(info.info.clone());
+            cycle.push(QueryInfo { span: info.job.span, query: info.query.clone() });
 
             if job == *self {
                 cycle.reverse();
@@ -170,7 +170,7 @@ pub(super) fn find_cycle_in_stack(
                     .job
                     .parent
                     .as_ref()
-                    .map(|parent| (info.info.span, parent.query(&query_map)));
+                    .map(|parent| (info.job.span, parent.query(&query_map)));
                 return CycleError { usage, cycle };
             }
 
@@ -591,10 +591,33 @@ pub(crate) fn report_cycle<'a>(
         err.span_note(span, &format!("...which requires {}...", query.description));
     }
 
-    err.note(&format!(
-        "...which again requires {}, completing the cycle",
-        stack[0].query.description
-    ));
+    if stack.len() == 1 {
+        err.note(&format!("...which immediately requires {} again", stack[0].query.description));
+    } else {
+        err.note(&format!(
+            "...which again requires {}, completing the cycle",
+            stack[0].query.description
+        ));
+    }
+
+    if stack.iter().all(|entry| {
+        entry.query.def_kind.map_or(false, |def_kind| {
+            matches!(def_kind, SimpleDefKind::TyAlias | SimpleDefKind::TraitAlias)
+        })
+    }) {
+        if stack.iter().all(|entry| {
+            entry
+                .query
+                .def_kind
+                .map_or(false, |def_kind| matches!(def_kind, SimpleDefKind::TyAlias))
+        }) {
+            err.note("type aliases cannot be recursive");
+            err.help("consider using a struct, enum, or union instead to break the cycle");
+            err.help("see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information");
+        } else {
+            err.note("trait aliases cannot be recursive");
+        }
+    }
 
     if let Some((span, query)) = usage {
         err.span_note(fix_span(span, &query), &format!("cycle used when {}", query.description));
@@ -626,13 +649,10 @@ pub fn print_query_stack<CTX: QueryContext>(
         };
         let mut diag = Diagnostic::new(
             Level::FailureNote,
-            &format!(
-                "#{} [{}] {}",
-                i, query_info.info.query.name, query_info.info.query.description
-            ),
+            &format!("#{} [{}] {}", i, query_info.query.name, query_info.query.description),
         );
         diag.span =
-            tcx.dep_context().sess().source_map().guess_head_span(query_info.info.span).into();
+            tcx.dep_context().sess().source_map().guess_head_span(query_info.job.span).into();
         handler.force_print_diagnostic(diag);
 
         current_query = query_info.job.parent;
index 7288aaef8f20beb4c7cdad1e0a1867717239652c..dffe7f3689ff4b52f80c4ff8af04b823a29bd9db 100644 (file)
@@ -29,24 +29,53 @@ pub struct QueryStackFrame {
     pub name: &'static str,
     pub description: String,
     span: Option<Span>,
+    /// The `DefKind` this query frame is associated with, if applicable.
+    ///
+    /// We can't use `rustc_hir::def::DefKind` because `rustc_hir` is not
+    /// available in `rustc_query_system`. Instead, we have a simplified
+    /// custom version of it, called [`SimpleDefKind`].
+    def_kind: Option<SimpleDefKind>,
     /// This hash is used to deterministically pick
     /// a query to remove cycles in the parallel compiler.
     #[cfg(parallel_compiler)]
     hash: u64,
 }
 
+/// A simplified version of `rustc_hir::def::DefKind`.
+///
+/// It was added to help improve cycle errors caused by recursive type aliases.
+/// As of August 2021, `rustc_query_system` cannot depend on `rustc_hir`
+/// because it would create a dependency cycle. So, instead, a simplified
+/// version of `DefKind` was added to `rustc_query_system`.
+///
+/// `DefKind`s are converted to `SimpleDefKind`s in `rustc_query_impl`.
+#[derive(Debug, Copy, Clone)]
+pub enum SimpleDefKind {
+    Struct,
+    Enum,
+    Union,
+    Trait,
+    TyAlias,
+    TraitAlias,
+
+    // FIXME: add more from `rustc_hir::def::DefKind` and then remove `Other`
+    Other,
+}
+
 impl QueryStackFrame {
     #[inline]
     pub fn new(
         name: &'static str,
         description: String,
         span: Option<Span>,
+        def_kind: Option<SimpleDefKind>,
         _hash: impl FnOnce() -> u64,
     ) -> Self {
         Self {
             name,
             description,
             span,
+            def_kind,
             #[cfg(parallel_compiler)]
             hash: _hash(),
         }
index a7511846cadb61abc218b1278a9ecd62bd27a8cf..3f22de6fba4077987d673cb21dfe8a4fea89b830 100644 (file)
@@ -130,8 +130,8 @@ pub fn try_collect_active_jobs<CTX: Copy>(
             for (k, v) in shard.active.iter() {
                 if let QueryResult::Started(ref job) = *v {
                     let id = QueryJobId::new(job.id, shard_id, kind);
-                    let info = QueryInfo { span: job.span, query: make_query(tcx, k.clone()) };
-                    jobs.insert(id, QueryJobInfo { info, job: job.clone() });
+                    let query = make_query(tcx, k.clone());
+                    jobs.insert(id, QueryJobInfo { query, job: job.clone() });
                 }
             }
         }
index ca2c22854c4f5d1bd9d2c9eaaaa76f79471b2456..0b1687d1bd8c3d4dbbdcc6103cae85eddae5a9f7 100644 (file)
@@ -506,8 +506,7 @@ impl<'a> Resolver<'a> {
 
                 if self.session.is_nightly_build() {
                     err.help(
-                        "use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` \
-                        to allow generic const expressions"
+                        "use `#![feature(generic_const_exprs)]` to allow generic const expressions",
                     );
                 }
 
index 0b552aa07f5179062631d70ea8347ffda0a206dd..60573968361203330f30e8f77c33ec89f8d15c81 100644 (file)
@@ -383,6 +383,11 @@ struct DiagnosticMetadata<'ast> {
     /// Only used for better errors on `fn(): fn()`.
     current_type_ascription: Vec<Span>,
 
+    /// Only used for better errors on `let x = { foo: bar };`.
+    /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only
+    /// needed for cases where this parses as a correct type ascription.
+    current_block_could_be_bare_struct_literal: Option<Span>,
+
     /// Only used for better errors on `let <pat>: <expr, not type>;`.
     current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,
 
@@ -454,7 +459,7 @@ fn visit_local(&mut self, local: &'ast Local) {
             _ => Some((
                 local.pat.span,
                 local.ty.as_ref().map(|ty| ty.span),
-                local.init.as_ref().map(|init| init.span),
+                local.kind.init().map(|init| init.span),
             )),
         };
         let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans);
@@ -952,6 +957,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
         match item.kind {
             ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _))
             | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => {
+                self.compute_num_lifetime_params(item.id, generics);
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     visit::walk_item(this, item)
                 });
@@ -960,6 +966,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
             ItemKind::Enum(_, ref generics)
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics) => {
+                self.compute_num_lifetime_params(item.id, generics);
                 self.resolve_adt(item, generics);
             }
 
@@ -970,10 +977,12 @@ fn resolve_item(&mut self, item: &'ast Item) {
                 items: ref impl_items,
                 ..
             }) => {
+                self.compute_num_lifetime_params(item.id, generics);
                 self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
             ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => {
+                self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     let local_def_id = this.r.local_def_id(item.id).to_def_id();
@@ -1025,6 +1034,7 @@ fn resolve_item(&mut self, item: &'ast Item) {
             }
 
             ItemKind::TraitAlias(ref generics, ref bounds) => {
+                self.compute_num_lifetime_params(item.id, generics);
                 // Create a new rib for the trait-wide type parameters.
                 self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
                     let local_def_id = this.r.local_def_id(item.id).to_def_id();
@@ -1276,7 +1286,14 @@ fn resolve_implementation(
             this.with_self_rib(Res::SelfTy(None, None), |this| {
                 // Resolve the trait reference, if necessary.
                 this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| {
-                    let item_def_id = this.r.local_def_id(item_id).to_def_id();
+                    let item_def_id = this.r.local_def_id(item_id);
+
+                    // Register the trait definitions from here.
+                    if let Some(trait_id) = trait_id {
+                        this.r.trait_impls.entry(trait_id).or_default().push(item_def_id);
+                    }
+
+                    let item_def_id = item_def_id.to_def_id();
                     this.with_self_rib(Res::SelfTy(trait_id, Some((item_def_id, false))), |this| {
                         if let Some(trait_ref) = opt_trait_reference.as_ref() {
                             // Resolve type arguments in the trait path.
@@ -1426,7 +1443,14 @@ fn resolve_local(&mut self, local: &'ast Local) {
         walk_list!(self, visit_ty, &local.ty);
 
         // Resolve the initializer.
-        walk_list!(self, visit_expr, &local.init);
+        if let Some((init, els)) = local.kind.init_else_opt() {
+            self.visit_expr(init);
+
+            // Resolve the `else` block
+            if let Some(els) = els {
+                self.visit_block(els);
+            }
+        }
 
         // Resolve the pattern.
         self.resolve_pattern_top(&local.pat, PatternSource::Let);
@@ -1852,6 +1876,7 @@ fn smart_resolve_path_fragment(
                 let instead = res.is_some();
                 let suggestion =
                     if res.is_none() { this.report_missing_type_error(path) } else { None };
+                // get_from_node_id
 
                 this.r.use_injections.push(UseError {
                     err,
@@ -2235,6 +2260,15 @@ fn resolve_block(&mut self, block: &'ast Block) {
             self.ribs[ValueNS].push(Rib::new(NormalRibKind));
         }
 
+        let prev = self.diagnostic_metadata.current_block_could_be_bare_struct_literal.take();
+        if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
+            (block.could_be_bare_literal, &block.stmts[..])
+        {
+            if let ExprKind::Type(..) = expr.kind {
+                self.diagnostic_metadata.current_block_could_be_bare_struct_literal =
+                    Some(block.span);
+            }
+        }
         // Descend into the block.
         for stmt in &block.stmts {
             if let StmtKind::Item(ref item) = stmt.kind {
@@ -2248,6 +2282,7 @@ fn resolve_block(&mut self, block: &'ast Block) {
 
             self.visit_stmt(stmt);
         }
+        self.diagnostic_metadata.current_block_could_be_bare_struct_literal = prev;
 
         // Move back up.
         self.parent_scope.module = orig_module;
@@ -2456,6 +2491,16 @@ fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate
             Some((ident.name, ns)),
         )
     }
+
+    fn compute_num_lifetime_params(&mut self, id: NodeId, generics: &Generics) {
+        let def_id = self.r.local_def_id(id);
+        let count = generics
+            .params
+            .iter()
+            .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
+            .count();
+        self.r.item_generics_num_lifetimes.insert(def_id, count);
+    }
 }
 
 impl<'a> Resolver<'a> {
index 9d923599db7619608399a4299bfcae000b073579..b2c0c7874655e0d6fe9fd6bf7a412ab1b5a4fb3b 100644 (file)
@@ -207,6 +207,16 @@ pub(crate) fn smart_resolve_report_errors(
         let code = source.error_code(res.is_some());
         let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
 
+        if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal {
+            err.multipart_suggestion(
+                "you might have meant to write a `struct` literal",
+                vec![
+                    (span.shrink_to_lo(), "{ SomeStruct ".to_string()),
+                    (span.shrink_to_hi(), "}".to_string()),
+                ],
+                Applicability::HasPlaceholders,
+            );
+        }
         match (source, self.diagnostic_metadata.in_if_condition) {
             (PathSource::Expr(_), Some(Expr { span, kind: ExprKind::Assign(..), .. })) => {
                 err.span_suggestion_verbose(
@@ -215,7 +225,6 @@ pub(crate) fn smart_resolve_report_errors(
                     "let ".to_string(),
                     Applicability::MaybeIncorrect,
                 );
-                self.r.session.if_let_suggestions.borrow_mut().insert(*span);
             }
             _ => {}
         }
@@ -2091,7 +2100,7 @@ fn suggestion(&self, sugg: String) -> Option<(Span, String)> {
                                 self.is_unnamed(),
                                 self.is_underscore(),
                                 self.is_named(),
-                                sugg.starts_with("&"),
+                                sugg.starts_with('&'),
                             ) {
                                 (true, _, _, false) => (self.span_unnamed_borrow(), sugg),
                                 (true, _, _, true) => {
@@ -2246,7 +2255,7 @@ fn span_underscore_borrow(&self) -> Span {
     }
 
     /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
-    /// This function will emit an error if `const_generics` is not enabled, the body identified by
+    /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
     /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
     crate fn maybe_emit_forbidden_non_static_lifetime_error(
         &self,
@@ -2265,7 +2274,7 @@ fn span_underscore_borrow(&self) -> Span {
         if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
             feature_err(
                 &self.tcx.sess.parse_sess,
-                sym::const_generics,
+                sym::generic_const_exprs,
                 lifetime_ref.span,
                 "a non-static lifetime is not allowed in a `const`",
             )
index 882d15cf8920f43beaa8ca9e435b6eb74891ba32..4c1d537d55fa37cd3231337c248630f6f5e48ec3 100644 (file)
@@ -740,6 +740,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
 
             hir::ItemKind::ExternCrate(_)
             | hir::ItemKind::Use(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..) => {
@@ -2300,7 +2301,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
             match *scope {
                 Scope::Body { id, s } => {
                     // Non-static lifetimes are prohibited in anonymous constants without
-                    // `const_generics`.
+                    // `generic_const_exprs`.
                     self.maybe_emit_forbidden_non_static_lifetime_error(id, lifetime_ref);
 
                     outermost_body = Some(id);
@@ -2604,8 +2605,10 @@ fn visit_segment_args(
                     binding.ident,
                 );
                 self.with(scope, |_, this| {
-                    let scope =
-                        Scope::Supertrait { lifetimes: lifetimes.unwrap_or(vec![]), s: this.scope };
+                    let scope = Scope::Supertrait {
+                        lifetimes: lifetimes.unwrap_or_default(),
+                        s: this.scope,
+                    };
                     this.with(scope, |_, this| this.visit_assoc_type_binding(binding));
                 });
             } else {
index e308ea1a1be5b0e1787a5c0b2c4db314dd3fd9b6..152d34fd63558df8e2c8caac358cae5b6f7f8608 100644 (file)
@@ -60,7 +60,7 @@
 
 use smallvec::{smallvec, SmallVec};
 use std::cell::{Cell, RefCell};
-use std::collections::BTreeSet;
+use std::collections::{BTreeMap, BTreeSet};
 use std::ops::ControlFlow;
 use std::{cmp, fmt, iter, ptr};
 use tracing::debug;
@@ -1030,8 +1030,14 @@ pub struct Resolver<'a> {
     trait_impl_items: FxHashSet<LocalDefId>,
 
     legacy_const_generic_args: FxHashMap<DefId, Option<Vec<usize>>>,
+    /// Amount of lifetime parameters for each item in the crate.
+    item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>,
 
     main_def: Option<MainDefinition>,
+    trait_impls: BTreeMap<DefId, Vec<LocalDefId>>,
+    /// A list of proc macro LocalDefIds, written out in the order in which
+    /// they are declared in the static array generated by proc_macro_harness.
+    proc_macros: Vec<NodeId>,
 }
 
 /// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1109,8 +1115,12 @@ fn def_key(&mut self, id: DefId) -> DefKey {
         }
     }
 
-    fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {
-        self.cstore().item_generics_num_lifetimes(def_id, sess)
+    fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
+        if let Some(def_id) = def_id.as_local() {
+            self.item_generics_num_lifetimes[&def_id]
+        } else {
+            self.cstore().item_generics_num_lifetimes(def_id, self.session)
+        }
     }
 
     fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
@@ -1390,7 +1400,10 @@ pub fn new(
             next_disambiguator: Default::default(),
             trait_impl_items: Default::default(),
             legacy_const_generic_args: Default::default(),
+            item_generics_num_lifetimes: Default::default(),
             main_def: Default::default(),
+            trait_impls: Default::default(),
+            proc_macros: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1425,6 +1438,7 @@ pub fn arenas() -> ResolverArenas<'a> {
     }
 
     pub fn into_outputs(self) -> ResolverOutputs {
+        let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
         let definitions = self.definitions;
         let visibilities = self.visibilities;
         let extern_crate_map = self.extern_crate_map;
@@ -1448,10 +1462,13 @@ pub fn into_outputs(self) -> ResolverOutputs {
                 .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
                 .collect(),
             main_def,
+            trait_impls: self.trait_impls,
+            proc_macros,
         }
     }
 
     pub fn clone_outputs(&self) -> ResolverOutputs {
+        let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
         ResolverOutputs {
             definitions: self.definitions.clone(),
             cstore: Box::new(self.cstore().clone()),
@@ -1467,6 +1484,8 @@ pub fn clone_outputs(&self) -> ResolverOutputs {
                 .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
                 .collect(),
             main_def: self.main_def.clone(),
+            trait_impls: self.trait_impls.clone(),
+            proc_macros,
         }
     }
 
@@ -2734,10 +2753,7 @@ fn validate_res_from_ribs(
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
-                            if !(trivial
-                                || features.const_generics
-                                || features.lazy_normalization_consts)
-                            {
+                            if !(trivial || features.generic_const_exprs) {
                                 // HACK(min_const_generics): If we encounter `Self` in an anonymous constant
                                 // we can't easily tell if it's generic at this stage, so we instead remember
                                 // this and then enforce the self type to be concrete later on.
@@ -2809,10 +2825,7 @@ fn validate_res_from_ribs(
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
-                            if !(trivial
-                                || features.const_generics
-                                || features.lazy_normalization_consts)
-                            {
+                            if !(trivial || features.generic_const_exprs) {
                                 if record_used {
                                     self.report_error(
                                         span,
index 7f86f891c4450039b11c5bb9974672a24fe6342e..6dc3aa0888a8be605c2e114ecb6555cdd3db28a4 100644 (file)
@@ -466,6 +466,10 @@ fn cfg_accessible(
     fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
         self.crate_loader.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
     }
+
+    fn declare_proc_macro(&mut self, id: NodeId) {
+        self.proc_macros.push(id)
+    }
 }
 
 impl<'a> Resolver<'a> {
index 29068761d6d843849770cd1889ff57576628fc1c..08ed9ec73c87570147544a84ea217de9e448f281 100644 (file)
@@ -1122,7 +1122,7 @@ pub(crate) fn process_crate(&mut self, krate: &'tcx hir::Crate<'tcx>) {
                 attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
             },
         );
-        intravisit::walk_crate(self, krate);
+        self.tcx.hir().walk_toplevel_module(self);
     }
 
     fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
index 0a8a88132e33de65849e710a2d069da135a1c5d6..41d174cde0a8ca0d3999641bda02efc5fdbf3b88 100644 (file)
@@ -1,5 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(if_let_guard)]
 #![feature(nll)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 mod dump_visitor;
@@ -326,54 +328,53 @@ pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
                     attributes: lower_attributes(attrs.to_vec(), self),
                 }))
             }
-            hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. }) => {
-                if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind {
-                    // Common case impl for a struct or something basic.
-                    if generated_code(path.span) {
-                        return None;
-                    }
-                    let sub_span = path.segments.last().unwrap().ident.span;
-                    filter!(self.span_utils, sub_span);
+            hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. })
+                if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind =>
+            {
+                // Common case impl for a struct or something basic.
+                if generated_code(path.span) {
+                    return None;
+                }
+                let sub_span = path.segments.last().unwrap().ident.span;
+                filter!(self.span_utils, sub_span);
 
-                    let impl_id = self.next_impl_id();
-                    let span = self.span_from_span(sub_span);
+                let impl_id = self.next_impl_id();
+                let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_def_id(self_ty.hir_id);
-                    type_data.map(|type_data| {
-                        Data::RelationData(
-                            Relation {
-                                kind: RelationKind::Impl { id: impl_id },
-                                span: span.clone(),
-                                from: id_from_def_id(type_data),
-                                to: of_trait
-                                    .as_ref()
-                                    .and_then(|t| self.lookup_def_id(t.hir_ref_id))
-                                    .map(id_from_def_id)
-                                    .unwrap_or_else(null_id),
-                            },
-                            Impl {
-                                id: impl_id,
-                                kind: match *of_trait {
-                                    Some(_) => ImplKind::Direct,
-                                    None => ImplKind::Inherent,
-                                },
-                                span,
-                                value: String::new(),
-                                parent: None,
-                                children: items
-                                    .iter()
-                                    .map(|i| id_from_def_id(i.id.def_id.to_def_id()))
-                                    .collect(),
-                                docs: String::new(),
-                                sig: None,
-                                attributes: vec![],
+                let type_data = self.lookup_def_id(self_ty.hir_id);
+                type_data.map(|type_data| {
+                    Data::RelationData(
+                        Relation {
+                            kind: RelationKind::Impl { id: impl_id },
+                            span: span.clone(),
+                            from: id_from_def_id(type_data),
+                            to: of_trait
+                                .as_ref()
+                                .and_then(|t| self.lookup_def_id(t.hir_ref_id))
+                                .map(id_from_def_id)
+                                .unwrap_or_else(null_id),
+                        },
+                        Impl {
+                            id: impl_id,
+                            kind: match *of_trait {
+                                Some(_) => ImplKind::Direct,
+                                None => ImplKind::Inherent,
                             },
-                        )
-                    })
-                } else {
-                    None
-                }
+                            span,
+                            value: String::new(),
+                            parent: None,
+                            children: items
+                                .iter()
+                                .map(|i| id_from_def_id(i.id.def_id.to_def_id()))
+                                .collect(),
+                            docs: String::new(),
+                            sig: None,
+                            attributes: vec![],
+                        },
+                    )
+                })
             }
+            hir::ItemKind::Impl(_) => None,
             _ => {
                 // FIXME
                 bug!();
index c3bc1c191ff09bdcdd6a4912560427153bd68959..7864b47ab0a7f429decd27730ceaeffef2f3da2d 100644 (file)
@@ -416,6 +416,14 @@ fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<
 
                 Ok(sig)
             }
+            hir::ItemKind::Macro(_) => {
+                let mut text = "macro".to_owned();
+                let name = self.ident.to_string();
+                text.push_str(&name);
+                text.push_str(&"! {}");
+
+                Ok(text_sig(text))
+            }
             hir::ItemKind::Mod(ref _mod) => {
                 let mut text = "mod ".to_owned();
                 let name = self.ident.to_string();
index 123f47b430a170c183e1ab7fce62f750b605f8b7..fdedb7e6a4afe9b2334822fd8afcf0d576f5e0cf 100644 (file)
@@ -1089,10 +1089,11 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         ),
         opt::flag_s("", "test", "Build a test harness"),
         opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
-        opt::multi_s("W", "warn", "Set lint warnings", "OPT"),
-        opt::multi_s("A", "allow", "Set lint allowed", "OPT"),
-        opt::multi_s("D", "deny", "Set lint denied", "OPT"),
-        opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
+        opt::multi_s("A", "allow", "Set lint allowed", "LINT"),
+        opt::multi_s("W", "warn", "Set lint warnings", "LINT"),
+        opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"),
+        opt::multi_s("D", "deny", "Set lint denied", "LINT"),
+        opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"),
         opt::multi_s(
             "",
             "cap-lints",
@@ -1101,13 +1102,6 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
              level",
             "LEVEL",
         ),
-        opt::multi_s(
-            "",
-            "force-warn",
-            "Specifiy lints that should warn even if \
-             they are allowed somewhere else",
-            "LINT",
-        ),
         opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
         opt::flag_s("V", "version", "Print version info and exit"),
         opt::flag_s("v", "verbose", "Use verbose output"),
@@ -1163,19 +1157,10 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
-    debugging_opts: &DebuggingOptions,
 ) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
-    if !debugging_opts.unstable_options && matches.opt_present("force-warn") {
-        early_error(
-            error_format,
-            "the `-Z unstable-options` flag must also be passed to enable \
-            the flag `--force-warn=lints`",
-        );
-    }
-
     for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] {
         for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
             if lint_name == "help" {
@@ -1965,8 +1950,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
-    let (lint_opts, describe_lints, lint_cap) =
-        get_cmd_lint_options(matches, error_format, &debugging_opts);
+    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
 
index f36fc29e9741716ef351f63212da8f15a302771a..9a1be40558ccb3ca03796f97f6381065301b455e 100644 (file)
@@ -1186,6 +1186,9 @@ mod parse {
         "support compiling tests with panic=abort (default: no)"),
     parse_only: bool = (false, parse_bool, [UNTRACKED],
         "parse only; do not compile, assemble, or link (default: no)"),
+    partially_uninit_const_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
+        "allow generating const initializers with mixed init/uninit bytes, \
+        and set the maximum total size of a const allocation for which this is allowed (default: never)"),
     perf_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some performance-related statistics (default: no)"),
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
index d49ba861785b3e19efdcc93050aee92befa36e15..0f7db69fefefc779cb66adc8035bb8a330dfb45f 100644 (file)
@@ -170,15 +170,9 @@ pub struct Session {
     /// Data about code being compiled, gathered during compilation.
     pub code_stats: CodeStats,
 
-    /// If `-zfuel=crate=n` is specified, `Some(crate)`.
-    optimization_fuel_crate: Option<String>,
-
     /// Tracks fuel info if `-zfuel=crate=n` is specified.
     optimization_fuel: Lock<OptimizationFuel>,
 
-    // The next two are public because the driver needs to read them.
-    /// If `-zprint-fuel=crate`, `Some(crate)`.
-    pub print_fuel_crate: Option<String>,
     /// Always set to zero and incremented so that we can print fuel expended by a crate.
     pub print_fuel: AtomicU64,
 
@@ -189,9 +183,6 @@ pub struct Session {
     /// Cap lint level specified by a driver specifically.
     pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
 
-    /// `Span`s of trait methods that weren't found to avoid emitting object safety errors
-    pub trait_methods_not_found: Lock<FxHashSet<Span>>,
-
     /// Mapping from ident span to path span for paths that don't exist as written, but that
     /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`.
     pub confused_type_with_std_module: Lock<FxHashMap<Span, Span>>,
@@ -199,6 +190,9 @@ pub struct Session {
     /// Tracks the current behavior of the CTFE engine when an error occurs.
     /// Options range from returning the error without a backtrace to returning an error
     /// and immediately printing the backtrace to stderr.
+    /// The `Lock` is only used by miri to allow setting `ctfe_backtrace` after analysis when
+    /// `MIRI_BACKTRACE` is set. This makes it only apply to miri's errors and not to all CTFE
+    /// errors.
     pub ctfe_backtrace: Lock<CtfeBacktrace>,
 
     /// This tracks where `-Zunleash-the-miri-inside-of-you` was used to get around a
@@ -212,9 +206,6 @@ pub struct Session {
 
     /// Set of enabled features for the current target.
     pub target_features: FxHashSet<Symbol>,
-
-    /// `Span`s for `if` conditions that we have suggested turning into `if let`.
-    pub if_let_suggestions: Lock<FxHashSet<Span>>,
 }
 
 pub struct PerfStats {
@@ -896,7 +887,7 @@ pub fn print_perf_stats(&self) {
     /// This expends fuel if applicable, and records fuel if applicable.
     pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
         let mut ret = true;
-        if let Some(ref c) = self.optimization_fuel_crate {
+        if let Some(c) = self.opts.debugging_opts.fuel.as_ref().map(|i| &i.0) {
             if c == crate_name {
                 assert_eq!(self.threads(), 1);
                 let mut fuel = self.optimization_fuel.lock();
@@ -909,7 +900,7 @@ pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -
                 }
             }
         }
-        if let Some(ref c) = self.print_fuel_crate {
+        if let Some(ref c) = self.opts.debugging_opts.print_fuel {
             if c == crate_name {
                 assert_eq!(self.threads(), 1);
                 self.print_fuel.fetch_add(1, SeqCst);
@@ -1267,12 +1258,10 @@ pub fn build_session(
     let local_crate_source_file =
         local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
 
-    let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
     let optimization_fuel = Lock::new(OptimizationFuel {
         remaining: sopts.debugging_opts.fuel.as_ref().map_or(0, |i| i.1),
         out_of_fuel: false,
     });
-    let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
     let print_fuel = AtomicU64::new(0);
 
     let cgu_reuse_tracker = if sopts.debugging_opts.query_dep_graph {
@@ -1320,19 +1309,15 @@ pub fn build_session(
             normalize_projection_ty: AtomicUsize::new(0),
         },
         code_stats: Default::default(),
-        optimization_fuel_crate,
         optimization_fuel,
-        print_fuel_crate,
         print_fuel,
         jobserver: jobserver::client(),
         driver_lint_caps,
-        trait_methods_not_found: Lock::new(Default::default()),
         confused_type_with_std_module: Lock::new(Default::default()),
         ctfe_backtrace,
         miri_unleashed_features: Lock::new(Default::default()),
         asm_arch,
         target_features: FxHashSet::default(),
-        if_let_suggestions: Default::default(),
     };
 
     validate_commandline_args_with_session_available(&sess);
index 8544acd6d05eebbb8b30f7d26b1bb83691f72dc9..511c2e8662697dfba808a918644bce81afdd4457 100644 (file)
@@ -32,7 +32,7 @@ pub enum Edition {
 
 pub const DEFAULT_EDITION: Edition = Edition::Edition2015;
 
-pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2018;
+pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2021;
 
 impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -66,7 +66,7 @@ pub fn is_stable(&self) -> bool {
         match *self {
             Edition::Edition2015 => true,
             Edition::Edition2018 => true,
-            Edition::Edition2021 => false,
+            Edition::Edition2021 => true,
         }
     }
 }
index e44a2e96598ce40401b244eeae6bfdaf1fd50854..c22093c5a428811ac78241029325969330873b41 100644 (file)
@@ -1097,6 +1097,7 @@ pub enum DesugaringKind {
     Async,
     Await,
     ForLoop(ForLoopLoc),
+    LetElse,
 }
 
 /// A location in the desugaring of a `for` loop
@@ -1117,6 +1118,7 @@ pub fn descr(self) -> &'static str {
             DesugaringKind::TryBlock => "`try` block",
             DesugaringKind::OpaqueTy => "`impl Trait`",
             DesugaringKind::ForLoop(_) => "`for` loop",
+            DesugaringKind::LetElse => "`let...else`",
         }
     }
 }
index 9e127577b61a664c8d75b1b561603c650923de73..b4cc8b2b4a3edcaa20b61b15776aa9aa8d09fa90 100644 (file)
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
+#![feature(if_let_guard)]
 #![feature(negative_impls)]
 #![feature(nll)]
 #![feature(min_specialization)]
 #![feature(thread_local_const_init)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 
 #[macro_use]
 extern crate rustc_macros;
@@ -258,11 +260,12 @@ pub fn local_path_if_available(&self) -> &Path {
         }
     }
 
-    pub fn to_string_lossy(&self, prefer_local: bool) -> Cow<'_, str> {
-        if prefer_local {
-            self.local_path_if_available().to_string_lossy()
-        } else {
-            self.remapped_path_if_available().to_string_lossy()
+    pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> {
+        match display_pref {
+            FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(),
+            FileNameDisplayPreference::Remapped => {
+                self.remapped_path_if_available().to_string_lossy()
+            }
         }
     }
 }
@@ -298,9 +301,15 @@ fn from(p: PathBuf) -> Self {
     }
 }
 
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
+pub enum FileNameDisplayPreference {
+    Remapped,
+    Local,
+}
+
 pub struct FileNameDisplay<'a> {
     inner: &'a FileName,
-    prefer_local: bool,
+    display_pref: FileNameDisplayPreference,
 }
 
 impl fmt::Display for FileNameDisplay<'_> {
@@ -308,7 +317,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use FileName::*;
         match *self.inner {
             Real(ref name) => {
-                write!(fmt, "{}", name.to_string_lossy(self.prefer_local))
+                write!(fmt, "{}", name.to_string_lossy(self.display_pref))
             }
             QuoteExpansion(_) => write!(fmt, "<quote expansion>"),
             MacroExpansion(_) => write!(fmt, "<macro expansion>"),
@@ -326,7 +335,7 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 impl FileNameDisplay<'_> {
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
         match self.inner {
-            FileName::Real(ref inner) => inner.to_string_lossy(self.prefer_local),
+            FileName::Real(ref inner) => inner.to_string_lossy(self.display_pref),
             _ => Cow::from(format!("{}", self)),
         }
     }
@@ -350,13 +359,17 @@ pub fn is_real(&self) -> bool {
     }
 
     pub fn prefer_remapped(&self) -> FileNameDisplay<'_> {
-        FileNameDisplay { inner: self, prefer_local: false }
+        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
     }
 
     // This may include transient local filesystem information.
     // Must not be embedded in build outputs.
     pub fn prefer_local(&self) -> FileNameDisplay<'_> {
-        FileNameDisplay { inner: self, prefer_local: true }
+        FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
+    }
+
+    pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> {
+        FileNameDisplay { inner: self, display_pref }
     }
 
     pub fn macro_expansion_source_code(src: &str) -> FileName {
@@ -595,6 +608,14 @@ pub fn parent(self) -> Option<Span> {
         if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
     }
 
+    /// Walk down the expansion ancestors to find a span that's contained within `outer`.
+    pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
+        while !outer.contains(self) {
+            self = self.parent()?;
+        }
+        Some(self)
+    }
+
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
         self.ctxt().edition()
index f700397fcdf0d28e220ec917a851500f1f87ffc1..9b8c8594ee843e88d5a4546a5566cfd624a8ed69 100644 (file)
@@ -427,7 +427,7 @@ pub fn lookup_line(&self, pos: BytePos) -> Result<SourceFileAndLine, Lrc<SourceF
         }
     }
 
-    fn span_to_string(&self, sp: Span, prefer_local: bool) -> String {
+    fn span_to_string(&self, sp: Span, filename_display_pref: FileNameDisplayPreference) -> String {
         if self.files.borrow().source_files.is_empty() || sp.is_dummy() {
             return "no-location".to_string();
         }
@@ -436,7 +436,7 @@ fn span_to_string(&self, sp: Span, prefer_local: bool) -> String {
         let hi = self.lookup_char_pos(sp.hi());
         format!(
             "{}:{}:{}: {}:{}",
-            if prefer_local { lo.file.name.prefer_local() } else { lo.file.name.prefer_remapped() },
+            lo.file.name.display(filename_display_pref),
             lo.line,
             lo.col.to_usize() + 1,
             hi.line,
@@ -446,20 +446,24 @@ fn span_to_string(&self, sp: Span, prefer_local: bool) -> String {
 
     /// Format the span location suitable for embedding in build artifacts
     pub fn span_to_embeddable_string(&self, sp: Span) -> String {
-        self.span_to_string(sp, false)
+        self.span_to_string(sp, FileNameDisplayPreference::Remapped)
     }
 
     /// Format the span location to be printed in diagnostics. Must not be emitted
     /// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
     /// for string suitable for embedding.
     pub fn span_to_diagnostic_string(&self, sp: Span) -> String {
-        self.span_to_string(sp, true)
+        self.span_to_string(sp, self.path_mapping.filename_display_for_diagnostics)
     }
 
     pub fn span_to_filename(&self, sp: Span) -> FileName {
         self.lookup_char_pos(sp.lo()).file.name.clone()
     }
 
+    pub fn filename_for_diagnostics<'a>(&self, filename: &'a FileName) -> FileNameDisplay<'a> {
+        filename.display(self.path_mapping.filename_display_for_diagnostics)
+    }
+
     pub fn is_multiline(&self, sp: Span) -> bool {
         let lo = self.lookup_source_file_idx(sp.lo());
         let hi = self.lookup_source_file_idx(sp.hi());
@@ -567,6 +571,17 @@ fn span_to_source<F, T>(&self, sp: Span, extract_source: F) -> Result<T, SpanSni
         }
     }
 
+    /// Returns whether or not this span points into a file
+    /// in the current crate. This may be `false` for spans
+    /// produced by a macro expansion, or for spans associated
+    /// with the definition of an item in a foreign crate
+    pub fn is_local_span(&self, sp: Span) -> bool {
+        let local_begin = self.lookup_byte_offset(sp.lo());
+        let local_end = self.lookup_byte_offset(sp.hi());
+        // This might be a weird span that covers multiple files
+        local_begin.sf.src.is_some() && local_end.sf.src.is_some()
+    }
+
     /// Returns the source snippet as `String` corresponding to the given `Span`.
     pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> {
         self.span_to_source(sp, |src, start_index, end_index| {
@@ -982,15 +997,13 @@ pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, Str
         None
     }
     pub fn ensure_source_file_source_present(&self, source_file: Lrc<SourceFile>) -> bool {
-        source_file.add_external_src(|| match source_file.name {
-            FileName::Real(ref name) => {
-                if let Some(local_path) = name.local_path() {
+        source_file.add_external_src(|| {
+            match source_file.name {
+                FileName::Real(ref name) if let Some(local_path) = name.local_path() => {
                     self.file_loader.read_file(local_path).ok()
-                } else {
-                    None
                 }
+                _ => None,
             }
-            _ => None,
         })
     }
 
@@ -1004,15 +1017,22 @@ pub fn is_imported(&self, sp: Span) -> bool {
 #[derive(Clone)]
 pub struct FilePathMapping {
     mapping: Vec<(PathBuf, PathBuf)>,
+    filename_display_for_diagnostics: FileNameDisplayPreference,
 }
 
 impl FilePathMapping {
     pub fn empty() -> FilePathMapping {
-        FilePathMapping { mapping: vec![] }
+        FilePathMapping::new(Vec::new())
     }
 
     pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping {
-        FilePathMapping { mapping }
+        let filename_display_for_diagnostics = if mapping.is_empty() {
+            FileNameDisplayPreference::Local
+        } else {
+            FileNameDisplayPreference::Remapped
+        };
+
+        FilePathMapping { mapping, filename_display_for_diagnostics }
     }
 
     /// Applies any path prefix substitution as defined by the mapping.
@@ -1033,22 +1053,19 @@ pub fn map_prefix(&self, path: PathBuf) -> (PathBuf, bool) {
 
     fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
         match file {
-            FileName::Real(realfile) => {
-                if let RealFileName::LocalPath(local_path) = realfile {
-                    let (mapped_path, mapped) = self.map_prefix(local_path.to_path_buf());
-                    let realfile = if mapped {
-                        RealFileName::Remapped {
-                            local_path: Some(local_path.clone()),
-                            virtual_name: mapped_path,
-                        }
-                    } else {
-                        realfile.clone()
-                    };
-                    (FileName::Real(realfile), mapped)
+            FileName::Real(realfile) if let RealFileName::LocalPath(local_path) = realfile => {
+                let (mapped_path, mapped) = self.map_prefix(local_path.to_path_buf());
+                let realfile = if mapped {
+                    RealFileName::Remapped {
+                        local_path: Some(local_path.clone()),
+                        virtual_name: mapped_path,
+                    }
                 } else {
-                    unreachable!("attempted to remap an already remapped filename");
-                }
+                    realfile.clone()
+                };
+                (FileName::Real(realfile), mapped)
             }
+            FileName::Real(_) => unreachable!("attempted to remap an already remapped filename"),
             other => (other.clone(), false),
         }
     }
index f788eb7d2126e53e5502b452a884ee2e75e82e02..24023163cc30eb2b2ca072313f21f421f86b5764 100644 (file)
         add_assign,
         add_with_overflow,
         address,
+        adt_const_params,
         advanced_slice_patterns,
         adx_target_feature,
         alias,
         core_panic_macro,
         cosf32,
         cosf64,
+        cr,
         crate_id,
         crate_in_paths,
         crate_local,
         generators,
         generic_arg_infer,
         generic_associated_types,
+        generic_const_exprs,
         generic_param_attrs,
         get_context,
         global_allocator,
         le,
         len,
         let_chains,
+        let_else,
         lhs,
         lib,
         libc,
         wreg,
         write_bytes,
         x87_reg,
+        xer,
         xmm_reg,
         ymm_reg,
         zmm_reg,
index aa8fd30452761c6c4a1a86da2b8ea2c70ce3ebed..aebf77a1fd85ffc1e276068968eea533c387f3da 100644 (file)
@@ -9,7 +9,7 @@ doctest = false
 [dependencies]
 tracing = "0.1"
 punycode = "0.4.0"
-rustc-demangle = "0.1.18"
+rustc-demangle = "0.1.21"
 
 rustc_span = { path = "../rustc_span" }
 rustc_middle = { path = "../rustc_middle" }
index 1b4e6b4e38177bf658afb1a8907098323df6ae05..e236ef996bcc6034fc0a3dfacade4ce5fb42097f 100644 (file)
@@ -107,9 +107,9 @@ fn get_symbol_hash<'tcx>(
         tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher);
 
         // Include the main item-type. Note that, in this case, the
-        // assertions about `needs_subst` may not hold, but this item-type
+        // assertions about `definitely_needs_subst` may not hold, but this item-type
         // ought to be the same for every reference anyway.
-        assert!(!item_type.has_erasable_regions());
+        assert!(!item_type.has_erasable_regions(tcx));
         hcx.while_hashing_spans(false, |hcx| {
             hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
                 item_type.hash_stable(hcx, &mut hasher);
index 850d44eb339c72e7c737297f76166317abdae290..220c9f7e2ec2bbeca37d4835041743be5d7e2e3f 100644 (file)
@@ -91,6 +91,7 @@
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -245,10 +246,18 @@ fn compute_symbol_name(
         tcx.symbol_mangling_version(mangling_version_crate)
     };
 
-    match mangling_version {
+    let symbol = match mangling_version {
         SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
         SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
-    }
+    };
+
+    debug_assert!(
+        rustc_demangle::try_demangle(&symbol).is_ok(),
+        "compute_symbol_name: `{}` cannot be demangled",
+        symbol
+    );
+
+    symbol
 }
 
 fn is_generic(substs: SubstsRef<'_>) -> bool {
index c4c1ec8ce4e0a2ca109d6aa669dc4802a9dec415..521730dfeb01cc22266da68404b104321abf2c39 100644 (file)
@@ -1,8 +1,10 @@
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
+use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -11,6 +13,7 @@
 use rustc_target::spec::abi::Abi;
 
 use std::fmt::Write;
+use std::iter;
 use std::ops::Range;
 
 pub(super) fn mangle(
@@ -277,7 +280,9 @@ fn print_impl_path(
 
         // Encode impl generic params if the substitutions contain parameters (implying
         // polymorphization is enabled) and this isn't an inherent impl.
-        if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
+        if impl_trait_ref.is_some()
+            && substs.iter().any(|a| a.definitely_has_param_types_or_consts(self.tcx))
+        {
             self = self.path_generic_args(
                 |this| {
                     this.path_append_ns(
@@ -534,39 +539,153 @@ fn print_dyn_existential(
     }
 
     fn print_const(mut self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
+        // We only mangle a typed value if the const can be evaluated.
+        let ct = ct.eval(self.tcx, ty::ParamEnv::reveal_all());
+        match ct.val {
+            ty::ConstKind::Value(_) => {}
+
+            // Placeholders (should be demangled as `_`).
+            // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
+            // a path), even for it we still need to encode a placeholder, as
+            // the path could refer back to e.g. an `impl` using the constant.
+            ty::ConstKind::Unevaluated(_)
+            | ty::ConstKind::Param(_)
+            | ty::ConstKind::Infer(_)
+            | ty::ConstKind::Bound(..)
+            | ty::ConstKind::Placeholder(_)
+            | ty::ConstKind::Error(_) => {
+                // Never cached (single-character).
+                self.push("p");
+                return Ok(self);
+            }
+        }
+
         if let Some(&i) = self.consts.get(&ct) {
             return self.print_backref(i);
         }
         let start = self.out.len();
 
-        let mut neg = false;
-        let val = match ct.ty.kind() {
-            ty::Uint(_) | ty::Bool | ty::Char => {
-                ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty)
-            }
-            ty::Int(ity) => {
-                ct.try_eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty).and_then(|b| {
-                    let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(b) as i128;
+        match ct.ty.kind() {
+            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
+                self = ct.ty.print(self)?;
+
+                let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty);
+
+                // Negative integer values are mangled using `n` as a "sign prefix".
+                if let ty::Int(ity) = ct.ty.kind() {
+                    let val =
+                        Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
-                        neg = true;
+                        self.push("n");
                     }
-                    Some(val.unsigned_abs())
-                })
+                    bits = val.unsigned_abs();
+                }
+
+                let _ = write!(self.out, "{:x}_", bits);
             }
+
+            // HACK(eddyb) because `ty::Const` only supports sized values (for now),
+            // we can't use `deref_const` + supporting `str`, we have to specially
+            // handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
+            ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
+                self.push("R");
+                match ct.val {
+                    ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
+                        // NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
+                        // 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 s = std::str::from_utf8(slice).expect("non utf8 str from miri");
+
+                        self.push("e");
+                        // FIXME(eddyb) use a specialized hex-encoding loop.
+                        for byte in s.bytes() {
+                            let _ = write!(self.out, "{:02x}", byte);
+                        }
+                        self.push("_");
+                    }
+
+                    _ => {
+                        bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
+                    }
+                }
+            }
+
+            ty::Ref(_, _, mutbl) => {
+                self.push(match mutbl {
+                    hir::Mutability::Not => "R",
+                    hir::Mutability::Mut => "Q",
+                });
+                self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
+            }
+
+            ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
+                let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
+                let fields = contents.fields.iter().copied();
+
+                let print_field_list = |mut this: Self| {
+                    for field in fields.clone() {
+                        this = field.print(this)?;
+                    }
+                    this.push("E");
+                    Ok(this)
+                };
+
+                match *ct.ty.kind() {
+                    ty::Array(..) => {
+                        self.push("A");
+                        self = print_field_list(self)?;
+                    }
+                    ty::Tuple(..) => {
+                        self.push("T");
+                        self = print_field_list(self)?;
+                    }
+                    ty::Adt(def, substs) => {
+                        let variant_idx =
+                            contents.variant.expect("destructed const of adt without variant idx");
+                        let variant_def = &def.variants[variant_idx];
+
+                        self.push("V");
+                        self = self.print_def_path(variant_def.def_id, substs)?;
+
+                        match variant_def.ctor_kind {
+                            CtorKind::Const => {
+                                self.push("U");
+                            }
+                            CtorKind::Fn => {
+                                self.push("T");
+                                self = print_field_list(self)?;
+                            }
+                            CtorKind::Fictive => {
+                                self.push("S");
+                                for (field_def, field) in iter::zip(&variant_def.fields, fields) {
+                                    // HACK(eddyb) this mimics `path_append`,
+                                    // instead of simply using `field_def.ident`,
+                                    // just to be able to handle disambiguators.
+                                    let disambiguated_field =
+                                        self.tcx.def_key(field_def.did).disambiguated_data;
+                                    let field_name =
+                                        disambiguated_field.data.get_opt_name().map(|s| s.as_str());
+                                    self.push_disambiguator(
+                                        disambiguated_field.disambiguator as u64,
+                                    );
+                                    self.push_ident(&field_name.as_ref().map_or("", |s| &s[..]));
+
+                                    self = field.print(self)?;
+                                }
+                                self.push("E");
+                            }
+                        }
+                    }
+                    _ => unreachable!(),
+                }
+            }
+
             _ => {
                 bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty, ct);
             }
-        };
-
-        if let Some(bits) = val {
-            // We only print the type if the const can be evaluated.
-            self = ct.ty.print(self)?;
-            let _ = write!(self.out, "{}{:x}_", if neg { "n" } else { "" }, bits);
-        } else {
-            // NOTE(eddyb) despite having the path, we need to
-            // encode a placeholder, as the path could refer
-            // back to e.g. an `impl` using the constant.
-            self.push("p");
         }
 
         // Only cache consts that do not refer to an enclosing
index a5e985d4712711c57d3e14217fcd7752a43c1338..4613a459c51d6d281dcf09d14b39d9fa3a16c2e3 100644 (file)
@@ -1,10 +1,10 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         let size = arg.layout.size;
@@ -26,8 +26,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -48,8 +48,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
@@ -70,8 +70,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
index 0b4f279fece403908221547dfa88f4cdffa5b89f..9be97476ce8f09efc49d83d6aa76684c1abf72c3 100644 (file)
@@ -1,26 +1,26 @@
 use crate::abi::call::{ArgAbi, FnAbi};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     ret.extend_integer_width_to(32);
 }
 
 fn classify_arg<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.extend_integer_width_to(32);
 }
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
index b560e11fe1c5e0ecb9ef8810377eb0ac61550c1f..e66c2132b8677b824f740007517cb8389ac4eab1 100644 (file)
@@ -1,11 +1,11 @@
 use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         let size = arg.layout.size;
@@ -27,8 +27,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -53,8 +53,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
@@ -75,8 +75,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     // If this is a target with a hard-float ABI, and the function is not explicitly
     // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
index 733a7328bd3a005648d99cf26006cfaa23c335c4..cc443197680e47c6aea6df744dbd6e0f4a158d07 100644 (file)
@@ -1,10 +1,9 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, Size};
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -14,10 +13,9 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
     }
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let dl = cx.data_layout();
     let size = arg.layout.size;
@@ -35,10 +33,9 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
     *offset = offset.align_to(align) + size.align_to(align);
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
+pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let mut offset = Size::ZERO;
     if !fn_abi.ret.is_ignore() {
index a630c84142b4d4ebb4f749ff68097bbcfa615d96..28ca93c46921e1cd7f69e770f89e99a7c722b40b 100644 (file)
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
@@ -19,8 +19,8 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
 
 fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     match ret.layout.field(cx, i).abi {
         abi::Abi::Scalar(ref scalar) => match scalar.value {
@@ -34,8 +34,8 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         extend_integer_width_mips(ret, 64);
@@ -74,8 +74,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         extend_integer_width_mips(arg, 64);
@@ -144,8 +144,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
index 6e0e140374033c3c2eef6ae53780160e3b9090c0..6d3c7318091076fbcbb0b2f7b5fab6c70ef5cfc7 100644 (file)
@@ -1,5 +1,5 @@
 use crate::abi::{self, Abi, Align, FieldsShape, Size};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::{self, HasTargetSpec};
 
 mod aarch64;
@@ -316,8 +316,7 @@ fn is_aggregate(&self) -> bool {
     /// specific targets.
     pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = Self>,
+        Ty: TyAbiInterface<'a, C> + Copy,
     {
         match self.abi {
             Abi::Uninhabited => Err(Heterogeneous),
@@ -603,8 +602,8 @@ pub struct FnAbi<'a, Ty> {
 impl<'a, Ty> FnAbi<'a, Ty> {
     pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+        Ty: TyAbiInterface<'a, C> + Copy,
+        C: HasDataLayout + HasTargetSpec,
     {
         if abi == spec::abi::Abi::X86Interrupt {
             if let Some(arg) = self.args.first_mut() {
index 8c2a9d09a3d9a8d27eb8be29d82fc3197471ebb5..c22ef9c8f2a7f54d19448901a0ad939055939f76 100644 (file)
@@ -3,7 +3,7 @@
 // need to be fixed when PowerPC vector support is added.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{Endian, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{Endian, HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
@@ -19,8 +19,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(
     abi: ABI,
 ) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         // ELFv1 only passes one-member aggregates transparently.
@@ -43,8 +43,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
@@ -86,8 +86,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
@@ -116,8 +116,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     let abi = if cx.target_spec().env == "musl" {
         ELFv2
index 1ab881dd13d1c46a1e8d5f4e0e0b7519fc115ff7..8c2ef8c7a017dfe130e2ac1799faee0241fdaff3 100644 (file)
@@ -5,9 +5,7 @@
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
 use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{
-    self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
-};
+use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(Copy, Clone)]
@@ -43,8 +41,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
     field2_kind: &mut RegPassKind,
 ) -> Result<(), CannotUseFpConv>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     match arg_layout.abi {
         Abi::Scalar(ref scalar) => match scalar.value {
@@ -130,8 +127,7 @@ fn should_use_fp_conv<'a, Ty, C>(
     flen: u64,
 ) -> Option<FloatConv>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     let mut field1_kind = RegPassKind::Unknown;
     let mut field2_kind = RegPassKind::Unknown;
@@ -149,8 +145,7 @@ fn should_use_fp_conv<'a, Ty, C>(
 
 fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
         match conv {
@@ -212,8 +207,7 @@ fn classify_arg<'a, Ty, C>(
     avail_gprs: &mut u64,
     avail_fprs: &mut u64,
 ) where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
+    Ty: TyAbiInterface<'a, C> + Copy,
 {
     if !is_vararg {
         match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
@@ -320,8 +314,8 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     let flen = match &cx.target_spec().llvm_abiname[..] {
         "ilp32f" | "lp64f" => 32,
index 005dcc62dfdc193cedeff6f5a633494e222234ec..594108925de8093e4ac90159ab035c714aff2c9b 100644 (file)
@@ -2,13 +2,9 @@
 // for a pre-z13 machine or using -mno-vx.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg};
-use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
 
-fn classify_ret<'a, Ty, C>(ret: &mut ArgAbi<'_, Ty>)
-where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
-{
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
     if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
         ret.extend_integer_width_to(64);
     } else {
@@ -18,8 +14,8 @@ fn classify_ret<'a, Ty, C>(ret: &mut ArgAbi<'_, Ty>)
 
 fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C>,
+    C: HasDataLayout,
 {
     match layout.abi {
         abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
@@ -36,8 +32,8 @@ fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
         arg.extend_integer_width_to(64);
@@ -63,8 +59,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(&mut fn_abi.ret);
index 733a7328bd3a005648d99cf26006cfaa23c335c4..cc443197680e47c6aea6df744dbd6e0f4a158d07 100644 (file)
@@ -1,10 +1,9 @@
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, Size};
 
-fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
@@ -14,10 +13,9 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
     }
 }
 
-fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
+fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let dl = cx.data_layout();
     let size = arg.layout.size;
@@ -35,10 +33,9 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
     *offset = offset.align_to(align) + size.align_to(align);
 }
 
-pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
+pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C>,
-    C: LayoutOf<Ty = Ty> + HasDataLayout,
+    C: HasDataLayout,
 {
     let mut offset = Size::ZERO;
     if !fn_abi.ret.is_ignore() {
index a647675e0735b8a0464034dec4cf4564461c7a39..5d74c94e2c6f67c32c91632f1642115822425061 100644 (file)
@@ -1,12 +1,12 @@
 // FIXME: This needs an audit for correctness and completeness.
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
         // Ensure we have at most eight uniquely addressable members.
@@ -26,8 +26,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Opti
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
@@ -52,8 +52,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
@@ -76,8 +76,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
index bf2c08bb1662d96df6957c349f636f35eb68dc84..3237cde10654ac4a1a70120843f95fb74165c8ed 100644 (file)
@@ -1,10 +1,10 @@
 use crate::abi::call::{ArgAbi, FnAbi, Uniform};
-use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if val.layout.is_aggregate() {
         if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
@@ -20,8 +20,8 @@ fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
 
 fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     ret.extend_integer_width_to(32);
     if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) {
@@ -31,8 +31,8 @@ fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
 
 fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     arg.extend_integer_width_to(32);
     if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
@@ -43,8 +43,8 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
 /// The purpose of this ABI is to match the C ABI (aka clang) exactly.
 pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     if !fn_abi.ret.is_ignore() {
         classify_ret(cx, &mut fn_abi.ret);
index ff8849e1cf83beac6293f686342379d49a33d964..3fc197b5d7537f494c7e830c776c19526b3324d5 100644 (file)
@@ -1,5 +1,5 @@
 use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
-use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(PartialEq)]
@@ -10,8 +10,8 @@ pub enum Flavor {
 
 fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     match layout.abi {
         abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
@@ -28,8 +28,8 @@ fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout + HasTargetSpec,
 {
     if !fn_abi.ret.is_ignore() {
         if fn_abi.ret.layout.is_aggregate() {
index a55658b7a3ec6caf1b2c30a5785a1fe04b146ea9..08f0aaba59af4891333db4179448682a8f314464 100644 (file)
@@ -2,7 +2,7 @@
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
 use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
-use crate::abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
+use crate::abi::{self, Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 
 /// Classification of "eightbyte" components.
 // N.B., the order of the variants is from general to specific,
@@ -26,8 +26,8 @@ fn classify_arg<'a, Ty, C>(
     arg: &ArgAbi<'a, Ty>,
 ) -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     fn classify<'a, Ty, C>(
         cx: &C,
@@ -36,8 +36,8 @@ fn classify<'a, Ty, C>(
         off: Size,
     ) -> Result<(), Memory>
     where
-        Ty: TyAndLayoutMethods<'a, C> + Copy,
-        C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+        Ty: TyAbiInterface<'a, C> + Copy,
+        C: HasDataLayout,
     {
         if !off.is_aligned(layout.align.abi) {
             if !layout.is_zst() {
@@ -172,8 +172,8 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget {
 
 pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
 where
-    Ty: TyAndLayoutMethods<'a, C> + Copy,
-    C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
+    Ty: TyAbiInterface<'a, C> + Copy,
+    C: HasDataLayout,
 {
     let mut int_regs = MAX_INT_REGS;
     let mut sse_regs = MAX_SSE_REGS;
index 8ef6e142caecfe02745d6a58cdddce78fd852af6..b0ecd117dd20e89b4016bcb6660cfc9cb19e9e9a 100644 (file)
@@ -5,6 +5,7 @@
 
 use std::convert::{TryFrom, TryInto};
 use std::fmt;
+use std::iter::Step;
 use std::num::NonZeroUsize;
 use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
 use std::str::FromStr;
@@ -12,7 +13,6 @@
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::json::{Json, ToJson};
-use rustc_span::Span;
 
 pub mod call;
 
@@ -193,6 +193,7 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
     /// address space on 64-bit ARMv8 and x86_64.
+    #[inline]
     pub fn obj_size_bound(&self) -> u64 {
         match self.pointer_size.bits() {
             16 => 1 << 15,
@@ -202,6 +203,7 @@ pub fn obj_size_bound(&self) -> u64 {
         }
     }
 
+    #[inline]
     pub fn ptr_sized_integer(&self) -> Integer {
         match self.pointer_size.bits() {
             16 => I16,
@@ -211,6 +213,7 @@ pub fn ptr_sized_integer(&self) -> Integer {
         }
     }
 
+    #[inline]
     pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
         for &(size, align) in &self.vector_align {
             if size == vec_size {
@@ -440,6 +443,43 @@ fn add_assign(&mut self, other: Size) {
     }
 }
 
+impl Step for Size {
+    #[inline]
+    fn steps_between(start: &Self, end: &Self) -> Option<usize> {
+        u64::steps_between(&start.bytes(), &end.bytes())
+    }
+
+    #[inline]
+    fn forward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::forward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn forward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
+    }
+
+    #[inline]
+    fn backward_checked(start: Self, count: usize) -> Option<Self> {
+        u64::backward_checked(start.bytes(), count).map(Self::from_bytes)
+    }
+
+    #[inline]
+    fn backward(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward(start.bytes(), count))
+    }
+
+    #[inline]
+    unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
+        Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
+    }
+}
+
 /// Alignment of a type in bytes (always a power of two).
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
@@ -524,14 +564,17 @@ pub struct AbiAndPrefAlign {
 }
 
 impl AbiAndPrefAlign {
+    #[inline]
     pub fn new(align: Align) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: align, pref: align }
     }
 
+    #[inline]
     pub fn min(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: self.abi.min(other.abi), pref: self.pref.min(other.pref) }
     }
 
+    #[inline]
     pub fn max(self, other: AbiAndPrefAlign) -> AbiAndPrefAlign {
         AbiAndPrefAlign { abi: self.abi.max(other.abi), pref: self.pref.max(other.pref) }
     }
@@ -548,6 +591,7 @@ pub enum Integer {
 }
 
 impl Integer {
+    #[inline]
     pub fn size(self) -> Size {
         match self {
             I8 => Size::from_bytes(1),
@@ -571,6 +615,7 @@ pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
     }
 
     /// Finds the smallest Integer type which can represent the signed value.
+    #[inline]
     pub fn fit_signed(x: i128) -> Integer {
         match x {
             -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8,
@@ -582,6 +627,7 @@ pub fn fit_signed(x: i128) -> Integer {
     }
 
     /// Finds the smallest Integer type which can represent the unsigned value.
+    #[inline]
     pub fn fit_unsigned(x: u128) -> Integer {
         match x {
             0..=0x0000_0000_0000_00ff => I8,
@@ -617,6 +663,9 @@ pub fn approximate_align<C: HasDataLayout>(cx: &C, wanted: Align) -> Integer {
         I8
     }
 
+    // FIXME(eddyb) consolidate this and other methods that find the appropriate
+    // `Integer` given some requirements.
+    #[inline]
     fn from_size(size: Size) -> Result<Self, String> {
         match size.bits() {
             8 => Ok(Integer::I8),
@@ -668,41 +717,94 @@ pub fn align<C: HasDataLayout>(self, cx: &C) -> AbiAndPrefAlign {
         }
     }
 
+    // FIXME(eddyb) remove, it's trivial thanks to `matches!`.
+    #[inline]
     pub fn is_float(self) -> bool {
         matches!(self, F32 | F64)
     }
 
+    // FIXME(eddyb) remove, it's completely unused.
+    #[inline]
     pub fn is_int(self) -> bool {
         matches!(self, Int(..))
     }
 }
 
+/// Inclusive wrap-around range of valid values, that is, if
+/// start > end, it represents `start..=MAX`,
+/// followed by `0..=end`.
+///
+/// That is, for an i8 primitive, a range of `254..=2` means following
+/// sequence:
+///
+///    254 (-2), 255 (-1), 0, 1, 2
+///
+/// This is intended specifically to mirror LLVM’s `!range` metadata,
+/// semantics.
+#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable_Generic)]
+pub struct WrappingRange {
+    pub start: u128,
+    pub end: u128,
+}
+
+impl WrappingRange {
+    /// Returns `true` if `v` is contained in the range.
+    #[inline(always)]
+    pub fn contains(&self, v: u128) -> bool {
+        if self.start <= self.end {
+            self.start <= v && v <= self.end
+        } else {
+            self.start <= v || v <= self.end
+        }
+    }
+
+    /// Returns `true` if zero is contained in the range.
+    /// Equal to `range.contains(0)` but should be faster.
+    #[inline(always)]
+    pub fn contains_zero(&self) -> bool {
+        self.start > self.end || self.start == 0
+    }
+
+    /// Returns `self` with replaced `start`
+    #[inline(always)]
+    pub fn with_start(mut self, start: u128) -> Self {
+        self.start = start;
+        self
+    }
+
+    /// Returns `self` with replaced `end`
+    #[inline(always)]
+    pub fn with_end(mut self, end: u128) -> Self {
+        self.end = end;
+        self
+    }
+}
+
+impl fmt::Debug for WrappingRange {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "{}..={}", self.start, self.end)?;
+        Ok(())
+    }
+}
+
 /// Information about one scalar component of a Rust type.
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
 
-    /// Inclusive wrap-around range of valid values, that is, if
-    /// start > end, it represents `start..=MAX`,
-    /// followed by `0..=end`.
-    ///
-    /// That is, for an i8 primitive, a range of `254..=2` means following
-    /// sequence:
-    ///
-    ///    254 (-2), 255 (-1), 0, 1, 2
-    ///
-    /// This is intended specifically to mirror LLVM’s `!range` metadata,
-    /// semantics.
     // FIXME(eddyb) always use the shortest range, e.g., by finding
     // the largest space between two consecutive valid values and
     // taking everything else as the (shortest) valid range.
-    pub valid_range: RangeInclusive<u128>,
+    pub valid_range: WrappingRange,
 }
 
 impl Scalar {
+    #[inline]
     pub fn is_bool(&self) -> bool {
-        matches!(self.value, Int(I8, false)) && self.valid_range == (0..=1)
+        matches!(self.value, Int(I8, false))
+            && matches!(self.valid_range, WrappingRange { start: 0, end: 1 })
     }
 
     /// Returns the valid range as a `x..y` range.
@@ -715,8 +817,8 @@ pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
         let bits = self.value.size(cx).bits();
         assert!(bits <= 128);
         let mask = !0u128 >> (128 - bits);
-        let start = *self.valid_range.start();
-        let end = *self.valid_range.end();
+        let start = self.valid_range.start;
+        let end = self.valid_range.end;
         assert_eq!(start, start & mask);
         assert_eq!(end, end & mask);
         start..(end.wrapping_add(1) & mask)
@@ -766,6 +868,7 @@ pub enum FieldsShape {
 }
 
 impl FieldsShape {
+    #[inline]
     pub fn count(&self) -> usize {
         match *self {
             FieldsShape::Primitive => 0,
@@ -775,6 +878,7 @@ pub fn count(&self) -> usize {
         }
     }
 
+    #[inline]
     pub fn offset(&self, i: usize) -> Size {
         match *self {
             FieldsShape::Primitive => {
@@ -798,6 +902,7 @@ pub fn offset(&self, i: usize) -> Size {
         }
     }
 
+    #[inline]
     pub fn memory_index(&self, i: usize) -> usize {
         match *self {
             FieldsShape::Primitive => {
@@ -881,6 +986,7 @@ pub fn is_unsized(&self) -> bool {
     }
 
     /// Returns `true` if this is a single signed integer scalar
+    #[inline]
     pub fn is_signed(&self) -> bool {
         match *self {
             Abi::Scalar(ref scal) => match scal.value {
@@ -971,14 +1077,14 @@ pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
         let max_value = !0u128 >> (128 - bits);
 
         // Find out how many values are outside the valid range.
-        let niche = v.end().wrapping_add(1)..*v.start();
+        let niche = v.end.wrapping_add(1)..v.start;
         niche.end.wrapping_sub(niche.start) & max_value
     }
 
     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
         assert!(count > 0);
 
-        let Scalar { value, valid_range: ref v } = self.scalar;
+        let Scalar { value, valid_range: v } = self.scalar.clone();
         let bits = value.size(cx).bits();
         assert!(bits <= 128);
         let max_value = !0u128 >> (128 - bits);
@@ -988,24 +1094,14 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
         }
 
         // Compute the range of invalid values being reserved.
-        let start = v.end().wrapping_add(1) & max_value;
-        let end = v.end().wrapping_add(count) & max_value;
-
-        // If the `end` of our range is inside the valid range,
-        // then we ran out of invalid values.
-        // FIXME(eddyb) abstract this with a wraparound range type.
-        let valid_range_contains = |x| {
-            if v.start() <= v.end() {
-                *v.start() <= x && x <= *v.end()
-            } else {
-                *v.start() <= x || x <= *v.end()
-            }
-        };
-        if valid_range_contains(end) {
+        let start = v.end.wrapping_add(1) & max_value;
+        let end = v.end.wrapping_add(count) & max_value;
+
+        if v.contains(end) {
             return None;
         }
 
-        Some((start, Scalar { value, valid_range: *v.start()..=end }))
+        Some((start, Scalar { value, valid_range: v.with_end(end) }))
     }
 }
 
@@ -1063,7 +1159,7 @@ pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
 /// to that obtained from `layout_of(ty)`, as we need to produce
 /// layouts for which Rust types do not exist, such as enum variants
 /// or synthetic fields of enums (i.e., discriminants) and fat pointers.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
 pub struct TyAndLayout<'a, Ty> {
     pub ty: Ty,
     pub layout: &'a Layout,
@@ -1076,49 +1172,6 @@ fn deref(&self) -> &&'a Layout {
     }
 }
 
-/// Trait for context types that can compute layouts of things.
-pub trait LayoutOf {
-    type Ty;
-    type TyAndLayout;
-
-    fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
-    fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
-        self.layout_of(ty)
-    }
-}
-
-/// The `TyAndLayout` above will always be a `MaybeResult<TyAndLayout<'_, Self>>`.
-/// We can't add the bound due to the lifetime, but this trait is still useful when
-/// writing code that's generic over the `LayoutOf` impl.
-pub trait MaybeResult<T> {
-    type Error;
-
-    fn from(x: Result<T, Self::Error>) -> Self;
-    fn to_result(self) -> Result<T, Self::Error>;
-}
-
-impl<T> MaybeResult<T> for T {
-    type Error = !;
-
-    fn from(Ok(x): Result<T, Self::Error>) -> Self {
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        Ok(self)
-    }
-}
-
-impl<T, E> MaybeResult<T> for Result<T, E> {
-    type Error = E;
-
-    fn from(x: Result<T, Self::Error>) -> Self {
-        x
-    }
-    fn to_result(self) -> Result<T, Self::Error> {
-        self
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
     /// Most general case, we know no restrictions to tell LLVM.
@@ -1142,41 +1195,42 @@ pub struct PointeeInfo {
     pub address_space: AddressSpace,
 }
 
-pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
-    fn for_variant(
+/// Trait that needs to be implemented by the higher-level type representation
+/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
+pub trait TyAbiInterface<'a, C>: Sized {
+    fn ty_and_layout_for_variant(
         this: TyAndLayout<'a, Self>,
         cx: &C,
         variant_index: VariantIdx,
     ) -> TyAndLayout<'a, Self>;
-    fn field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> C::TyAndLayout;
-    fn pointee_info_at(this: TyAndLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>;
+    fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>;
+    fn ty_and_layout_pointee_info_at(
+        this: TyAndLayout<'a, Self>,
+        cx: &C,
+        offset: Size,
+    ) -> Option<PointeeInfo>;
 }
 
 impl<'a, Ty> TyAndLayout<'a, Ty> {
     pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::for_variant(self, cx, variant_index)
+        Ty::ty_and_layout_for_variant(self, cx, variant_index)
     }
 
-    /// Callers might want to use `C: LayoutOf<Ty=Ty, TyAndLayout: MaybeResult<Self>>`
-    /// to allow recursion (see `might_permit_zero_init` below for an example).
-    pub fn field<C>(self, cx: &C, i: usize) -> C::TyAndLayout
+    pub fn field<C>(self, cx: &C, i: usize) -> Self
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::field(self, cx, i)
+        Ty::ty_and_layout_field(self, cx, i)
     }
 
     pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
     where
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty>,
+        Ty: TyAbiInterface<'a, C>,
     {
-        Ty::pointee_info_at(self, cx, offset)
+        Ty::ty_and_layout_pointee_info_at(self, cx, offset)
     }
 }
 
@@ -1204,17 +1258,16 @@ pub fn is_zst(&self) -> bool {
     /// FIXME: Once we removed all the conservatism, we could alternatively
     /// create an all-0/all-undef constant and run the const value validator to see if
     /// this is a valid value for the given type.
-    pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
+    pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
     where
         Self: Copy,
-        Ty: TyAndLayoutMethods<'a, C>,
-        C: LayoutOf<Ty = Ty, TyAndLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
+        Ty: TyAbiInterface<'a, C>,
+        C: HasDataLayout,
     {
         let scalar_allows_raw_init = move |s: &Scalar| -> bool {
             if zero {
-                let range = &s.valid_range;
                 // The range must contain 0.
-                range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0
+                s.valid_range.contains_zero()
             } else {
                 // The range must include all values. `valid_range_exclusive` handles
                 // the wrap-around using target arithmetic; with wrap-around then the full
@@ -1234,7 +1287,7 @@ pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
         };
         if !valid {
             // This is definitely not okay.
-            return Ok(false);
+            return false;
         }
 
         // If we have not found an error yet, we need to recursively descend into fields.
@@ -1245,16 +1298,15 @@ pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
             }
             FieldsShape::Arbitrary { offsets, .. } => {
                 for idx in 0..offsets.len() {
-                    let field = self.field(cx, idx).to_result()?;
-                    if !field.might_permit_raw_init(cx, zero)? {
+                    if !self.field(cx, idx).might_permit_raw_init(cx, zero) {
                         // We found a field that is unhappy with this kind of initialization.
-                        return Ok(false);
+                        return false;
                     }
                 }
             }
         }
 
         // FIXME(#66151): For now, we are conservative and do not check `self.variants`.
-        Ok(true)
+        true
     }
 }
index bb24f7bb135ef0b22e9cac3eb2353fbdd42a8c65..99699c50df584840734e16d38f2fb02e09633fe9 100644 (file)
@@ -154,6 +154,7 @@ macro_rules! types {
 mod nvptx;
 mod powerpc;
 mod riscv;
+mod s390x;
 mod spirv;
 mod wasm;
 mod x86;
@@ -166,6 +167,7 @@ macro_rules! types {
 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
 pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
+pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
 pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
 pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
@@ -184,6 +186,7 @@ pub enum InlineAsmArch {
     Mips64,
     PowerPC,
     PowerPC64,
+    S390x,
     SpirV,
     Wasm32,
     Bpf,
@@ -206,6 +209,7 @@ fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
             "hexagon" => Ok(Self::Hexagon),
             "mips" => Ok(Self::Mips),
             "mips64" => Ok(Self::Mips64),
+            "s390x" => Ok(Self::S390x),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
             "bpf" => Ok(Self::Bpf),
@@ -235,6 +239,7 @@ pub enum InlineAsmReg {
     PowerPC(PowerPCInlineAsmReg),
     Hexagon(HexagonInlineAsmReg),
     Mips(MipsInlineAsmReg),
+    S390x(S390xInlineAsmReg),
     SpirV(SpirVInlineAsmReg),
     Wasm(WasmInlineAsmReg),
     Bpf(BpfInlineAsmReg),
@@ -252,6 +257,7 @@ pub fn name(self) -> &'static str {
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::S390x(r) => r.name(),
             Self::Bpf(r) => r.name(),
             Self::Err => "<reg>",
         }
@@ -266,6 +272,7 @@ pub fn reg_class(self) -> InlineAsmRegClass {
             Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
             Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
             Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
+            Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
             Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Err => InlineAsmRegClass::Err,
         }
@@ -305,6 +312,9 @@ pub fn parse(
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
                 Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
+            InlineAsmArch::S390x => {
+                Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?)
+            }
             InlineAsmArch::SpirV => {
                 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
@@ -333,6 +343,7 @@ pub fn emit(
             Self::PowerPC(r) => r.emit(out, arch, modifier),
             Self::Hexagon(r) => r.emit(out, arch, modifier),
             Self::Mips(r) => r.emit(out, arch, modifier),
+            Self::S390x(r) => r.emit(out, arch, modifier),
             Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
@@ -344,9 +355,10 @@ pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
             Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
             Self::AArch64(_) => cb(self),
             Self::RiscV(_) => cb(self),
-            Self::PowerPC(_) => cb(self),
+            Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))),
             Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
             Self::Mips(_) => cb(self),
+            Self::S390x(_) => cb(self),
             Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
@@ -374,6 +386,7 @@ pub enum InlineAsmRegClass {
     PowerPC(PowerPCInlineAsmRegClass),
     Hexagon(HexagonInlineAsmRegClass),
     Mips(MipsInlineAsmRegClass),
+    S390x(S390xInlineAsmRegClass),
     SpirV(SpirVInlineAsmRegClass),
     Wasm(WasmInlineAsmRegClass),
     Bpf(BpfInlineAsmRegClass),
@@ -392,6 +405,7 @@ pub fn name(self) -> Symbol {
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::S390x(r) => r.name(),
             Self::SpirV(r) => r.name(),
             Self::Wasm(r) => r.name(),
             Self::Bpf(r) => r.name(),
@@ -412,6 +426,7 @@ pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Sel
             Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
             Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
             Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
+            Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
             Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
             Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
             Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
@@ -439,6 +454,7 @@ pub fn suggest_modifier(
             Self::PowerPC(r) => r.suggest_modifier(arch, ty),
             Self::Hexagon(r) => r.suggest_modifier(arch, ty),
             Self::Mips(r) => r.suggest_modifier(arch, ty),
+            Self::S390x(r) => r.suggest_modifier(arch, ty),
             Self::SpirV(r) => r.suggest_modifier(arch, ty),
             Self::Wasm(r) => r.suggest_modifier(arch, ty),
             Self::Bpf(r) => r.suggest_modifier(arch, ty),
@@ -462,6 +478,7 @@ pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str
             Self::PowerPC(r) => r.default_modifier(arch),
             Self::Hexagon(r) => r.default_modifier(arch),
             Self::Mips(r) => r.default_modifier(arch),
+            Self::S390x(r) => r.default_modifier(arch),
             Self::SpirV(r) => r.default_modifier(arch),
             Self::Wasm(r) => r.default_modifier(arch),
             Self::Bpf(r) => r.default_modifier(arch),
@@ -484,6 +501,7 @@ pub fn supported_types(
             Self::PowerPC(r) => r.supported_types(arch),
             Self::Hexagon(r) => r.supported_types(arch),
             Self::Mips(r) => r.supported_types(arch),
+            Self::S390x(r) => r.supported_types(arch),
             Self::SpirV(r) => r.supported_types(arch),
             Self::Wasm(r) => r.supported_types(arch),
             Self::Bpf(r) => r.supported_types(arch),
@@ -509,6 +527,7 @@ pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
                 Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
             }
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
@@ -527,6 +546,7 @@ pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
             Self::PowerPC(r) => r.valid_modifiers(arch),
             Self::Hexagon(r) => r.valid_modifiers(arch),
             Self::Mips(r) => r.valid_modifiers(arch),
+            Self::S390x(r) => r.valid_modifiers(arch),
             Self::SpirV(r) => r.valid_modifiers(arch),
             Self::Wasm(r) => r.valid_modifiers(arch),
             Self::Bpf(r) => r.valid_modifiers(arch),
@@ -695,6 +715,11 @@ pub fn allocatable_registers(
             mips::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
+        InlineAsmArch::S390x => {
+            let mut map = s390x::regclass_map();
+            s390x::fill_reg_map(arch, has_feature, target, &mut map);
+            map
+        }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
             spirv::fill_reg_map(arch, has_feature, target, &mut map);
index 42fc25c4ff565dafd1add85a27e09da27181d32c..51a4303689e67f64a39de6bf08fa9c7de0ab97cb 100644 (file)
@@ -7,6 +7,8 @@
         reg,
         reg_nonzero,
         freg,
+        cr,
+        xer,
     }
 }
 
@@ -44,6 +46,7 @@ pub fn supported_types(
                 }
             }
             Self::freg => types! { _: F32, F64; },
+            Self::cr | Self::xer => &[],
         }
     }
 }
@@ -108,6 +111,16 @@ pub fn supported_types(
         f29: freg = ["f29", "fr29"],
         f30: freg = ["f30", "fr30"],
         f31: freg = ["f31", "fr31"],
+        cr: cr = ["cr"],
+        cr0: cr = ["cr0"],
+        cr1: cr = ["cr1"],
+        cr2: cr = ["cr2"],
+        cr3: cr = ["cr3"],
+        cr4: cr = ["cr4"],
+        cr5: cr = ["cr5"],
+        cr6: cr = ["cr6"],
+        cr7: cr = ["cr7"],
+        xer: xer = ["xer"],
         #error = ["r1", "1", "sp"] =>
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["r2", "2"] =>
@@ -136,17 +149,55 @@ pub fn emit(
         _arch: InlineAsmArch,
         _modifier: Option<char>,
     ) -> fmt::Result {
+        macro_rules! do_emit {
+            (
+                $($(($reg:ident, $value:literal)),*;)*
+            ) => {
+                out.write_str(match self {
+                    $($(Self::$reg => $value,)*)*
+                })
+            };
+        }
         // Strip off the leading prefix.
-        if self as u32 <= Self::r28 as u32 {
-            let index = self as u32 - Self::r28 as u32;
-            write!(out, "{}", index)
-        } else if self as u32 >= Self::f0 as u32 && self as u32 <= Self::f31 as u32 {
-            let index = self as u32 - Self::f31 as u32;
-            write!(out, "{}", index)
-        } else {
-            unreachable!()
+        do_emit! {
+            (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
+            (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15");
+            (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
+            (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
+            (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
+            (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
+            (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
+            (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
+            (cr, "cr");
+            (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
+            (xer, "xer");
         }
     }
 
-    pub fn overlapping_regs(self, mut _cb: impl FnMut(PowerPCInlineAsmReg)) {}
+    pub fn overlapping_regs(self, mut cb: impl FnMut(PowerPCInlineAsmReg)) {
+        macro_rules! reg_conflicts {
+            (
+                $(
+                    $full:ident : $($field:ident)*
+                ),*;
+            ) => {
+                match self {
+                    $(
+                        Self::$full => {
+                            cb(Self::$full);
+                            $(cb(Self::$field);)*
+                        }
+                        $(Self::$field)|* => {
+                            cb(Self::$full);
+                            cb(self);
+                        }
+                    )*
+                    r => cb(r),
+                }
+            };
+        }
+        reg_conflicts! {
+            cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
+        }
+    }
 }
diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs
new file mode 100644 (file)
index 0000000..a74873f
--- /dev/null
@@ -0,0 +1,106 @@
+use super::{InlineAsmArch, InlineAsmType};
+use rustc_macros::HashStable_Generic;
+use std::fmt;
+
+def_reg_class! {
+    S390x S390xInlineAsmRegClass {
+        reg,
+        freg,
+    }
+}
+
+impl S390xInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+        match (self, arch) {
+            (Self::reg, _) => types! { _: I8, I16, I32, I64; },
+            (Self::freg, _) => types! { _: F32, F64; },
+        }
+    }
+}
+
+def_regs! {
+    S390x S390xInlineAsmReg S390xInlineAsmRegClass {
+        r0: reg = ["r0"],
+        r1: reg = ["r1"],
+        r2: reg = ["r2"],
+        r3: reg = ["r3"],
+        r4: reg = ["r4"],
+        r5: reg = ["r5"],
+        r6: reg = ["r6"],
+        r7: reg = ["r7"],
+        r8: reg = ["r8"],
+        r9: reg = ["r9"],
+        r10: reg = ["r10"],
+        r12: reg = ["r12"],
+        r13: reg = ["r13"],
+        r14: reg = ["r14"],
+        f0: freg = ["f0"],
+        f1: freg = ["f1"],
+        f2: freg = ["f2"],
+        f3: freg = ["f3"],
+        f4: freg = ["f4"],
+        f5: freg = ["f5"],
+        f6: freg = ["f6"],
+        f7: freg = ["f7"],
+        f8: freg = ["f8"],
+        f9: freg = ["f9"],
+        f10: freg = ["f10"],
+        f11: freg = ["f11"],
+        f12: freg = ["f12"],
+        f13: freg = ["f13"],
+        f14: freg = ["f14"],
+        f15: freg = ["f15"],
+        #error = ["r11"] =>
+            "The frame pointer cannot be used as an operand for inline asm",
+        #error = ["r15"] =>
+            "The stack pointer cannot be used as an operand for inline asm",
+        #error = [
+            "c0", "c1", "c2", "c3",
+            "c4", "c5", "c6", "c7",
+            "c8", "c9", "c10", "c11",
+            "c12", "c13", "c14", "c15"
+        ] =>
+            "control registers are reserved by the kernel and cannot be used as operands for inline asm",
+        #error = [
+            "a0", "a1", "a2", "a3",
+            "a4", "a5", "a6", "a7",
+            "a8", "a9", "a10", "a11",
+            "a12", "a13", "a14", "a15"
+        ] =>
+            "access registers are not supported and cannot be used as operands for inline asm",
+    }
+}
+
+impl S390xInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        write!(out, "%{}", self.name())
+    }
+}
index d39e5a5aa2c3f4bed54ec4272d7e50a94e808000..e75c52555b90347418bdb8255f7b7fe1d3b2bf72 100644 (file)
@@ -14,6 +14,8 @@
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 #![feature(min_specialization)]
+#![feature(step_trait)]
+#![feature(unchecked_math)]
 
 use std::path::{Path, PathBuf};
 
index ee36090c549513241c403c00020904780a90119b..e3a2226eb9d152a4a64f4d36da1be0b930b62849 100644 (file)
@@ -87,6 +87,9 @@ pub fn all_names() -> Vec<&'static str> {
 }
 
 impl Abi {
+    /// Default ABI chosen for `extern fn` declarations without an explicit ABI.
+    pub const FALLBACK: Abi = Abi::C { unwind: false };
+
     #[inline]
     pub fn index(self) -> usize {
         // N.B., this ordering MUST match the AbiDatas array above.
index 5d75f6ab39ce7e3f21b8852eb4eaf786c363d433..a21b784e11b1ca4578c3dd7454704e87720e0e1e 100644 (file)
@@ -1,6 +1,6 @@
 use std::env;
 
-use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions};
+use crate::spec::{FramePointer, LldFlavor, SplitDebuginfo, TargetOptions};
 
 pub fn opts(os: &str) -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
@@ -35,6 +35,7 @@ pub fn opts(os: &str) -> TargetOptions {
         abi_return_struct_as_int: true,
         emit_debug_gdb_scripts: false,
         eh_frame_header: false,
+        lld_flavor: LldFlavor::Ld64,
 
         // The historical default for macOS targets is to run `dsymutil` which
         // generates a packed version of debuginfo split from the main file.
index 911956859b8619b263b1e1c252627642bea512bd..273221360b8b561ca9d1d5d265956861369f6488 100644 (file)
@@ -664,7 +664,7 @@ fn to_json(&self) -> Json {
         self.into_iter()
             .map(|v| Some(v.as_str()?.to_json()))
             .collect::<Option<Vec<_>>>()
-            .unwrap_or(Vec::new())
+            .unwrap_or_default()
             .to_json()
     }
 }
@@ -1501,7 +1501,8 @@ pub fn is_abi_supported(&self, abi: Abi) -> Option<bool> {
             | Cdecl
             | EfiApi => true,
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
-            Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+            Aapcs => "arm" == self.arch,
+            CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
             Win64 | SysV64 => self.arch == "x86_64",
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
index b78e43d4fe9b6f842db4d179d5437936bfde8c8b..34b6d2901c82039010871fc2376b12c4a815ec9d 100644 (file)
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
@@ -8,6 +8,7 @@ pub fn target() -> Target {
     base.max_atomic_width = Some(64);
     // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
     base.stack_probes = StackProbeType::Call;
+    base.supported_sanitizers = SanitizerSet::ADDRESS;
 
     Target {
         llvm_target: "x86_64-pc-solaris".to_string(),
index d3f9349d99b8e6ec71fca6912b5141927d87fe62..ec196a7f823296d651a4ea9c8ead65122f29f4eb 100644 (file)
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{LinkerFlavor, SanitizerSet, Target};
 
 pub fn target() -> Target {
     let mut base = super::illumos_base::opts();
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string(), "-std=c99".to_string()]);
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
+    base.supported_sanitizers = SanitizerSet::ADDRESS;
 
     Target {
         // LLVM does not currently have a separate illumos target,
index ea074192d23b14262f97d2455e783b6978552bbb..c90649353e80f391b5739378a3bd29813bd5e22f 100644 (file)
@@ -44,6 +44,10 @@ fn partially_normalize_associated_types_in<T>(
     /// - the self type
     /// - the *other* type parameters of the trait, excluding the self-type
     /// - the parameter environment
+    ///
+    /// Invokes `evaluate_obligation`, so in the event that evaluating
+    /// `Ty: Trait` causes overflow, EvaluatedToRecur (or EvaluatedToUnknown)
+    /// will be returned.
     fn type_implements_trait(
         &self,
         trait_def_id: DefId,
@@ -117,7 +121,7 @@ fn type_implements_trait(
             recursion_depth: 0,
             predicate: trait_ref.without_const().to_predicate(self.tcx),
         };
-        self.evaluate_obligation_no_overflow(&obligation)
+        self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
     }
 }
 
index c5a6e301deba96c1d835da9e9d63d54116097411..b743c809ca2434926b49c0f80ee205744d366cd5 100644 (file)
@@ -352,6 +352,7 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         if !required_region_bounds.is_empty() {
             for required_region in required_region_bounds {
                 concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+                    tcx,
                     op: |r| self.sub_regions(infer::CallReturn(span), required_region, r),
                 });
             }
@@ -427,6 +428,7 @@ fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
             }
         }
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx,
             op: |r| self.sub_regions(infer::CallReturn(span), least_region, r),
         });
     }
@@ -461,6 +463,7 @@ fn generate_member_constraint(
         );
 
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+            tcx: self.tcx,
             op: |r| {
                 self.member_constraint(
                     opaque_type_key.def_id,
@@ -546,14 +549,19 @@ fn infer_opaque_definition_from_instantiation(
 //
 // We ignore any type parameters because impl trait values are assumed to
 // capture all the in-scope type parameters.
-struct ConstrainOpaqueTypeRegionVisitor<OP> {
+struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
+    tcx: TyCtxt<'tcx>,
     op: OP,
 }
 
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
 where
     OP: FnMut(ty::Region<'tcx>),
 {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &ty::Binder<'tcx, T>,
@@ -575,7 +583,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         // We're only interested in types involving regions
-        if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
+        if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
             return ControlFlow::CONTINUE;
         }
 
index 282502cfa0d3d8d73f2ed0ccc7871a6a84092387..622c9edc4345035b2af384334f8109d424489ac8 100644 (file)
@@ -285,7 +285,7 @@ fn evaluate_predicates(
                 def_id: trait_did,
                 substs: infcx.tcx.mk_substs_trait(ty, &[]),
             },
-            constness: hir::Constness::NotConst,
+            constness: ty::BoundConstness::NotConst,
         }));
 
         let computed_preds = param_env.caller_bounds().iter();
index 9bb4af16a8f53fac2637f0b5b531cacd554a0c01..668a74bd6971506b02351ac309a8b892db2661e8 100644 (file)
@@ -391,7 +391,7 @@ fn orphan_check_trait_ref<'tcx>(
 ) -> Result<(), OrphanCheckErr<'tcx>> {
     debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
 
-    if trait_ref.needs_infer() && trait_ref.needs_subst() {
+    if trait_ref.needs_infer() && trait_ref.definitely_needs_subst(tcx) {
         bug!(
             "can't orphan check a trait ref with both params and inference variables {:?}",
             trait_ref
index b1a938836b70ee1fff62cf28941327e124a5080e..ddabe5967d79cf9566fd923249ce4bfcc4658bae 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_session::lint;
-use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 
 use std::cmp;
 /// Check if a given constant can be evaluated.
 pub fn is_const_evaluatable<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
-    def: ty::WithOptConstParam<DefId>,
-    substs: SubstsRef<'tcx>,
+    uv: ty::Unevaluated<'tcx, ()>,
     param_env: ty::ParamEnv<'tcx>,
     span: Span,
 ) -> Result<(), NotConstEvaluatable> {
-    debug!("is_const_evaluatable({:?}, {:?})", def, substs);
-    if infcx.tcx.features().const_evaluatable_checked {
+    debug!("is_const_evaluatable({:?})", uv);
+    if infcx.tcx.features().generic_const_exprs {
         let tcx = infcx.tcx;
-        match AbstractConst::new(tcx, def, substs)? {
+        match AbstractConst::new(tcx, uv)? {
             // We are looking at a generic abstract constant.
             Some(ct) => {
                 for pred in param_env.caller_bounds() {
                     match pred.kind().skip_binder() {
-                        ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
-                            if b_def == def && b_substs == substs {
-                                debug!("is_const_evaluatable: caller_bound ~~> ok");
-                                return Ok(());
-                            }
-
-                            if let Some(b_ct) = AbstractConst::new(tcx, b_def, b_substs)? {
+                        ty::PredicateKind::ConstEvaluatable(uv) => {
+                            if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
                                 // Try to unify with each subtree in the AbstractConst to allow for
                                 // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
                                 // predicate for `(N + 1) * 2`
@@ -91,7 +85,7 @@ enum FailureKind {
                         let leaf = leaf.subst(tcx, ct.substs);
                         if leaf.has_infer_types_or_consts() {
                             failure_kind = FailureKind::MentionsInfer;
-                        } else if leaf.has_param_types_or_consts() {
+                        } else if leaf.definitely_has_param_types_or_consts(tcx) {
                             failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                         }
 
@@ -101,7 +95,7 @@ enum FailureKind {
                         let ty = ty.subst(tcx, ct.substs);
                         if ty.has_infer_types_or_consts() {
                             failure_kind = FailureKind::MentionsInfer;
-                        } else if ty.has_param_types_or_consts() {
+                        } else if ty.definitely_has_param_types_or_consts(tcx) {
                             failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
                         }
 
@@ -134,7 +128,7 @@ enum FailureKind {
     }
 
     let future_compat_lint = || {
-        if let Some(local_def_id) = def.did.as_local() {
+        if let Some(local_def_id) = uv.def.did.as_local() {
             infcx.tcx.struct_span_lint_hir(
                 lint::builtin::CONST_EVALUATABLE_UNCHECKED,
                 infcx.tcx.hir().local_def_id_to_hir_id(local_def_id),
@@ -155,16 +149,12 @@ enum FailureKind {
     // and hopefully soon change this to an error.
     //
     // See #74595 for more details about this.
-    let concrete = infcx.const_eval_resolve(
-        param_env,
-        ty::Unevaluated { def, substs, promoted: None },
-        Some(span),
-    );
-
-    if concrete.is_ok() && substs.has_param_types_or_consts() {
-        match infcx.tcx.def_kind(def.did) {
+    let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
+
+    if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
+        match infcx.tcx.def_kind(uv.def.did) {
             DefKind::AnonConst => {
-                let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
+                let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
 
                 if mir_body.is_polymorphic {
                     future_compat_lint();
@@ -176,7 +166,7 @@ enum FailureKind {
 
     debug!(?concrete, "is_const_evaluatable");
     match concrete {
-        Err(ErrorHandled::TooGeneric) => Err(match substs.has_infer_types_or_consts() {
+        Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
             true => NotConstEvaluatable::MentionsInfer,
             false => NotConstEvaluatable::MentionsParam,
         }),
@@ -201,15 +191,14 @@ pub struct AbstractConst<'tcx> {
     pub substs: SubstsRef<'tcx>,
 }
 
-impl AbstractConst<'tcx> {
+impl<'tcx> AbstractConst<'tcx> {
     pub fn new(
         tcx: TyCtxt<'tcx>,
-        def: ty::WithOptConstParam<DefId>,
-        substs: SubstsRef<'tcx>,
+        uv: ty::Unevaluated<'tcx, ()>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
-        let inner = tcx.mir_abstract_const_opt_const_arg(def)?;
-        debug!("AbstractConst::new({:?}) = {:?}", def, inner);
-        Ok(inner.map(|inner| AbstractConst { inner, substs }))
+        let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?;
+        debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
+        Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) }))
     }
 
     pub fn from_const(
@@ -217,9 +206,7 @@ pub fn from_const(
         ct: &ty::Const<'tcx>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
         match ct.val {
-            ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: _ }) => {
-                AbstractConst::new(tcx, def, substs)
-            }
+            ty::ConstKind::Unevaluated(uv) => AbstractConst::new(tcx, uv.shrink()),
             ty::ConstKind::Error(_) => Err(ErrorReported),
             _ => Ok(None),
         }
@@ -550,9 +537,9 @@ pub(super) fn mir_abstract_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
 ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
-    if tcx.features().const_evaluatable_checked {
+    if tcx.features().generic_const_exprs {
         match tcx.def_kind(def.did) {
-            // FIXME(const_evaluatable_checked): We currently only do this for anonymous constants,
+            // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
             // meaning that we do not look into associated constants. I(@lcnr) am not yet sure whether
             // we want to look into them or treat them as opaque projections.
             //
@@ -569,14 +556,11 @@ pub(super) fn mir_abstract_const<'tcx>(
 
 pub(super) fn try_unify_abstract_consts<'tcx>(
     tcx: TyCtxt<'tcx>,
-    ((a, a_substs), (b, b_substs)): (
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
-        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
-    ),
+    (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
 ) -> bool {
     (|| {
-        if let Some(a) = AbstractConst::new(tcx, a, a_substs)? {
-            if let Some(b) = AbstractConst::new(tcx, b, b_substs)? {
+        if let Some(a) = AbstractConst::new(tcx, a)? {
+            if let Some(b) = AbstractConst::new(tcx, b)? {
                 return Ok(try_unify(tcx, a, b));
             }
         }
@@ -584,7 +568,7 @@ pub(super) fn try_unify_abstract_consts<'tcx>(
         Ok(false)
     })()
     .unwrap_or_else(|ErrorReported| true)
-    // FIXME(const_evaluatable_checked): We should instead have this
+    // FIXME(generic_const_exprs): We should instead have this
     // method return the resulting `ty::Const` and return `ConstKind::Error`
     // on `ErrorReported`.
 }
@@ -672,13 +656,13 @@ pub(super) fn try_unify<'tcx>(
                 // branch should only be taking when dealing with associated constants, at
                 // which point directly comparing them seems like the desired behavior.
                 //
-                // FIXME(const_evaluatable_checked): This isn't actually the case.
+                // FIXME(generic_const_exprs): This isn't actually the case.
                 // We also take this branch for concrete anonymous constants and
                 // expand generic anonymous constants with concrete substs.
                 (ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => {
                     a_uv == b_uv
                 }
-                // FIXME(const_evaluatable_checked): We may want to either actually try
+                // FIXME(generic_const_exprs): We may want to either actually try
                 // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
                 // this, for now we just return false here.
                 _ => false,
index 90b6ee5f5a6a670b39e27a4251343e578cdff971..9ce6c58a0f1df4b81b08fbb494dff3458169a230 100644 (file)
@@ -16,6 +16,8 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
+use rustc_hir::GenericParam;
+use rustc_hir::Item;
 use rustc_hir::Node;
 use rustc_middle::mir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
@@ -224,7 +226,9 @@ fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !
 
         debug!("report_overflow_error_cycle: cycle={:?}", cycle);
 
-        self.report_overflow_error(&cycle[0], false);
+        // The 'deepest' obligation is most likely to have a useful
+        // cause 'backtrace'
+        self.report_overflow_error(cycle.iter().max_by_key(|p| p.recursion_depth).unwrap(), false);
     }
 
     fn report_selection_error(
@@ -794,7 +798,7 @@ fn report_selection_error(
                 )
             }
             SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => {
-                if !self.tcx.features().const_evaluatable_checked {
+                if !self.tcx.features().generic_const_exprs {
                     let mut err = self.tcx.sess.struct_span_err(
                         span,
                         "constant expression depends on a generic parameter",
@@ -803,7 +807,7 @@ fn report_selection_error(
                     // issue. However, this is currently not actually possible
                     // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
                     //
-                    // Note that with `feature(const_evaluatable_checked)` this case should not
+                    // Note that with `feature(generic_const_exprs)` this case should not
                     // be reachable.
                     err.note("this may fail depending on what value the parameter takes");
                     err.emit();
@@ -811,10 +815,10 @@ fn report_selection_error(
                 }
 
                 match obligation.predicate.kind().skip_binder() {
-                    ty::PredicateKind::ConstEvaluatable(def, _) => {
+                    ty::PredicateKind::ConstEvaluatable(uv) => {
                         let mut err =
                             self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
-                        let const_span = self.tcx.def_span(def.did);
+                        let const_span = self.tcx.def_span(uv.def.did);
                         match self.tcx.sess.source_map().span_to_snippet(const_span) {
                             Ok(snippet) => err.help(&format!(
                                 "try adding a `where` bound using this expression: `where [(); {}]:`",
@@ -1136,6 +1140,20 @@ fn suggest_unsized_bound_if_applicable(
         obligation: &PredicateObligation<'tcx>,
     );
 
+    fn maybe_suggest_unsized_generics(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        node: Node<'hir>,
+    );
+
+    fn maybe_indirection_for_unsized(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        item: &'hir Item<'hir>,
+        param: &'hir GenericParam<'hir>,
+    ) -> bool;
+
     fn is_recursive_obligation(
         &self,
         obligated_types: &mut Vec<&ty::TyS<'tcx>>,
@@ -1814,7 +1832,10 @@ fn suggest_unsized_bound_if_applicable(
                 ) => (pred, item_def_id, span),
                 _ => return,
             };
-
+        debug!(
+            "suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}",
+            pred, item_def_id, span
+        );
         let node = match (
             self.tcx.hir().get_if_local(item_def_id),
             Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
@@ -1822,80 +1843,105 @@ fn suggest_unsized_bound_if_applicable(
             (Some(node), true) => node,
             _ => return,
         };
+        self.maybe_suggest_unsized_generics(err, span, node);
+    }
+
+    fn maybe_suggest_unsized_generics(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        node: Node<'hir>,
+    ) {
         let generics = match node.generics() {
             Some(generics) => generics,
             None => return,
         };
-        for param in generics.params {
-            if param.span != span
-                || param.bounds.iter().any(|bound| {
-                    bound.trait_ref().and_then(|trait_ref| trait_ref.trait_def_id())
-                        == self.tcx.lang_items().sized_trait()
-                })
-            {
-                continue;
-            }
-            match node {
-                hir::Node::Item(
-                    item
-                    @
-                    hir::Item {
-                        kind:
-                            hir::ItemKind::Enum(..)
-                            | hir::ItemKind::Struct(..)
-                            | hir::ItemKind::Union(..),
-                        ..
-                    },
-                ) => {
-                    // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
-                    // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
-                    // is not.
-                    let mut visitor = FindTypeParam {
-                        param: param.name.ident().name,
-                        invalid_spans: vec![],
-                        nested: false,
-                    };
-                    visitor.visit_item(item);
-                    if !visitor.invalid_spans.is_empty() {
-                        let mut multispan: MultiSpan = param.span.into();
-                        multispan.push_span_label(
-                            param.span,
-                            format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
-                        );
-                        for sp in visitor.invalid_spans {
-                            multispan.push_span_label(
-                                sp,
-                                format!(
-                                    "...if indirection were used here: `Box<{}>`",
-                                    param.name.ident(),
-                                ),
-                            );
-                        }
-                        err.span_help(
-                            multispan,
-                            &format!(
-                                "you could relax the implicit `Sized` bound on `{T}` if it were \
-                                 used through indirection like `&{T}` or `Box<{T}>`",
-                                T = param.name.ident(),
-                            ),
-                        );
-                        return;
-                    }
+        let sized_trait = self.tcx.lang_items().sized_trait();
+        debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
+        debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause);
+        let param = generics
+            .params
+            .iter()
+            .filter(|param| param.span == span)
+            .filter(|param| {
+                // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
+                // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
+                param
+                    .bounds
+                    .iter()
+                    .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
+            })
+            .next();
+        let param = match param {
+            Some(param) => param,
+            _ => return,
+        };
+        debug!("maybe_suggest_unsized_generics: param={:?}", param);
+        match node {
+            hir::Node::Item(
+                item
+                @
+                hir::Item {
+                    // Only suggest indirection for uses of type parameters in ADTs.
+                    kind:
+                        hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..),
+                    ..
+                },
+            ) => {
+                if self.maybe_indirection_for_unsized(err, item, param) {
+                    return;
                 }
-                _ => {}
             }
-            let (span, separator) = match param.bounds {
-                [] => (span.shrink_to_hi(), ":"),
-                [.., bound] => (bound.span().shrink_to_hi(), " +"),
-            };
-            err.span_suggestion_verbose(
-                span,
-                "consider relaxing the implicit `Sized` restriction",
-                format!("{} ?Sized", separator),
-                Applicability::MachineApplicable,
+            _ => {}
+        };
+        // Didn't add an indirection suggestion, so add a general suggestion to relax `Sized`.
+        let (span, separator) = match param.bounds {
+            [] => (span.shrink_to_hi(), ":"),
+            [.., bound] => (bound.span().shrink_to_hi(), " +"),
+        };
+        err.span_suggestion_verbose(
+            span,
+            "consider relaxing the implicit `Sized` restriction",
+            format!("{} ?Sized", separator),
+            Applicability::MachineApplicable,
+        );
+    }
+
+    fn maybe_indirection_for_unsized(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        item: &'hir Item<'hir>,
+        param: &'hir GenericParam<'hir>,
+    ) -> bool {
+        // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
+        // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
+        // is not. Look for invalid "bare" parameter uses, and suggest using indirection.
+        let mut visitor =
+            FindTypeParam { param: param.name.ident().name, invalid_spans: vec![], nested: false };
+        visitor.visit_item(item);
+        if visitor.invalid_spans.is_empty() {
+            return false;
+        }
+        let mut multispan: MultiSpan = param.span.into();
+        multispan.push_span_label(
+            param.span,
+            format!("this could be changed to `{}: ?Sized`...", param.name.ident()),
+        );
+        for sp in visitor.invalid_spans {
+            multispan.push_span_label(
+                sp,
+                format!("...if indirection were used here: `Box<{}>`", param.name.ident()),
             );
-            return;
         }
+        err.span_help(
+            multispan,
+            &format!(
+                "you could relax the implicit `Sized` bound on `{T}` if it were \
+                used through indirection like `&{T}` or `Box<{T}>`",
+                T = param.name.ident(),
+            ),
+        );
+        true
     }
 
     fn is_recursive_obligation(
@@ -1946,6 +1992,7 @@ fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
                 if path.segments.len() == 1 && path.segments[0].ident.name == self.param =>
             {
                 if !self.nested {
+                    debug!("FindTypeParam::visit_ty: ty={:?}", ty);
                     self.invalid_spans.push(ty.span);
                 }
             }
index 40841a6e32d00e2cc97db003a445b919873e426c..db3432b01422fabe81afa2654993521cb3672be6 100644 (file)
@@ -1928,7 +1928,11 @@ fn note_obligation_cause_code<T>(
             | ObligationCauseCode::OpaqueType
             | ObligationCauseCode::MiscObligation
             | ObligationCauseCode::WellFormed(..)
-            | ObligationCauseCode::MatchImpl(..) => {}
+            | ObligationCauseCode::MatchImpl(..)
+            | ObligationCauseCode::ReturnType
+            | ObligationCauseCode::ReturnValue(_)
+            | ObligationCauseCode::BlockTailExpression(_)
+            | ObligationCauseCode::LetElse => {}
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
             }
@@ -2338,9 +2342,6 @@ fn note_obligation_cause_code<T>(
                     predicate
                 ));
             }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
             ObligationCauseCode::TrivialBound => {
                 err.help("see issue #48214");
                 if tcx.sess.opts.unstable_features.is_nightly_build() {
index 4b94deff825bdd7d7416882f1ec2e0e23c13f44a..18abcc72bcee8d013950671b67c558c7f305c163 100644 (file)
@@ -543,11 +543,10 @@ fn progress_changed_obligations(
                     }
                 }
 
-                ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+                ty::PredicateKind::ConstEvaluatable(uv) => {
                     match const_evaluatable::is_const_evaluatable(
                         self.selcx.infcx(),
-                        def_id,
-                        substs,
+                        uv,
                         obligation.param_env,
                         obligation.cause.span,
                     ) {
@@ -555,7 +554,9 @@ fn progress_changed_obligations(
                         Err(NotConstEvaluatable::MentionsInfer) => {
                             pending_obligation.stalled_on.clear();
                             pending_obligation.stalled_on.extend(
-                                substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
+                                uv.substs(infcx.tcx)
+                                    .iter()
+                                    .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
                             );
                             ProcessResult::Unchanged
                         }
@@ -570,7 +571,8 @@ fn progress_changed_obligations(
 
                 ty::PredicateKind::ConstEquate(c1, c2) => {
                     debug!(?c1, ?c2, "equating consts");
-                    if self.selcx.tcx().features().const_evaluatable_checked {
+                    let tcx = self.selcx.tcx();
+                    if tcx.features().generic_const_exprs {
                         // FIXME: we probably should only try to unify abstract constants
                         // if the constants depend on generic parameters.
                         //
@@ -578,7 +580,7 @@ fn progress_changed_obligations(
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
                             (c1.val, c2.val)
                         {
-                            if infcx.try_unify_abstract_consts(a, b) {
+                            if infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) {
                                 return ProcessResult::Changed(vec![]);
                             }
                         }
@@ -597,7 +599,7 @@ fn progress_changed_obligations(
                                 Err(ErrorHandled::TooGeneric) => {
                                     stalled_on.extend(
                                         unevaluated
-                                            .substs
+                                            .substs(tcx)
                                             .iter()
                                             .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
                                     );
@@ -668,7 +670,7 @@ fn process_trait_obligation(
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx();
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_known_global() {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             //
@@ -727,7 +729,7 @@ fn process_projection_obligation(
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
 
-        if obligation.predicate.is_global() {
+        if obligation.predicate.is_global(tcx) {
             // no type variables present, can use evaluation for better caching.
             // FIXME: consider caching errors too.
             //
@@ -766,14 +768,15 @@ fn substs_infer_vars<'a, 'tcx>(
     selcx: &mut SelectionContext<'a, 'tcx>,
     substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
 ) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
+    let tcx = selcx.tcx();
     selcx
         .infcx()
         .resolve_vars_if_possible(substs)
         .skip_binder() // ok because this check doesn't care about regions
         .iter()
         .filter(|arg| arg.has_infer_types_or_consts())
-        .flat_map(|arg| {
-            let mut walker = arg.walk();
+        .flat_map(move |arg| {
+            let mut walker = arg.walk(tcx);
             while let Some(c) = walker.next() {
                 if !c.has_infer_types_or_consts() {
                     walker.visited.remove(&c);
index 477d29f1a4fb94e9092de43ccb00ba627c764371..44c675243838a11e1213f6f5131af5edc5803db0 100644 (file)
@@ -450,7 +450,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
     debug!("subst_and_check_impossible_predicates(key={:?})", key);
 
     let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
-    predicates.retain(|predicate| !predicate.needs_subst());
+    predicates.retain(|predicate| !predicate.definitely_needs_subst(tcx));
     let result = impossible_predicates(tcx, predicates);
 
     debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
@@ -625,6 +625,31 @@ fn dump_vtable_entries<'tcx>(
     tcx.sess.struct_span_err(sp, &msg).emit();
 }
 
+fn own_existential_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyExistentialTraitRef<'tcx>,
+) -> &'tcx [DefId] {
+    let trait_methods = tcx
+        .associated_items(trait_ref.def_id())
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Fn);
+    // Now list each method's DefId (for within its trait).
+    let own_entries = trait_methods.filter_map(move |trait_method| {
+        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+        let def_id = trait_method.def_id;
+
+        // Some methods cannot be called on an object; skip those.
+        if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+            debug!("own_existential_vtable_entry: not vtable safe");
+            return None;
+        }
+
+        Some(def_id)
+    });
+
+    tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
 /// Given a trait `trait_ref`, iterates the vtable entries
 /// that come from `trait_ref`, including its supertraits.
 fn vtable_entries<'tcx>(
@@ -641,21 +666,15 @@ fn vtable_entries<'tcx>(
                 entries.extend(COMMON_VTABLE_ENTRIES);
             }
             VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                let trait_methods = tcx
-                    .associated_items(trait_ref.def_id())
-                    .in_definition_order()
-                    .filter(|item| item.kind == ty::AssocKind::Fn);
-                // Now list each method's DefId and InternalSubsts (for within its trait).
-                // If the method can never be called from this object, produce `Vacant`.
-                let own_entries = trait_methods.map(move |trait_method| {
-                    debug!("vtable_entries: trait_method={:?}", trait_method);
-                    let def_id = trait_method.def_id;
-
-                    // Some methods cannot be called on an object; skip those.
-                    if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
-                        debug!("vtable_entries: not vtable safe");
-                        return VtblEntry::Vacant;
-                    }
+                let existential_trait_ref = trait_ref
+                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+                // Lookup the shape of vtable for the trait.
+                let own_existential_entries =
+                    tcx.own_existential_vtable_entries(existential_trait_ref);
+
+                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+                    debug!("vtable_entries: trait_method={:?}", def_id);
 
                     // The method may have some early-bound lifetimes; add regions for those.
                     let substs = trait_ref.map_bound(|trait_ref| {
@@ -778,7 +797,10 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot(
     let obligation = Obligation::new(
         ObligationCause::dummy(),
         ty::ParamEnv::reveal_all(),
-        ty::Binder::dummy(ty::TraitPredicate { trait_ref, constness: hir::Constness::NotConst }),
+        ty::Binder::dummy(ty::TraitPredicate {
+            trait_ref,
+            constness: ty::BoundConstness::NotConst,
+        }),
     );
 
     let implsrc = tcx.infer_ctxt().enter(|infcx| {
@@ -801,6 +823,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
         codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+        own_existential_vtable_entries,
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
index 02b43de0d1606c0e425106fe1ff66d2294f51774..57b8a84300ff9e0db5464fc1759d913c0b6ae9c9 100644 (file)
@@ -278,7 +278,7 @@ fn predicate_references_self(
     (predicate, sp): (ty::Predicate<'tcx>, Span),
 ) -> Option<Span> {
     let self_ty = tcx.types.self_param;
-    let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
+    let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk(tcx).any(|arg| arg == self_ty.into());
     match predicate.kind().skip_binder() {
         ty::PredicateKind::Trait(ref data) => {
             // In the case of a trait predicate, we can skip the "self" type.
@@ -771,6 +771,9 @@ struct IllegalSelfTypeVisitor<'tcx> {
 
     impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
         type BreakTy = ();
+        fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+            Some(self.tcx)
+        }
 
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
@@ -817,10 +820,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             }
         }
 
-        fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
-            // First check if the type of this constant references `Self`.
-            self.visit_ty(ct.ty)?;
-
+        fn visit_unevaluated_const(
+            &mut self,
+            uv: ty::Unevaluated<'tcx>,
+        ) -> ControlFlow<Self::BreakTy> {
             // Constants can only influence object safety if they reference `Self`.
             // This is only possible for unevaluated constants, so we walk these here.
             //
@@ -834,7 +837,7 @@ fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             // This shouldn't really matter though as we can't really use any
             // constants which are not considered const evaluatable.
             use rustc_middle::mir::abstract_const::Node;
-            if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
+            if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
                 const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
                     Node::Leaf(leaf) => {
                         let leaf = leaf.subst(self.tcx, ct.substs);
@@ -849,31 +852,6 @@ fn visit_const(&mut self, ct: &ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
                 ControlFlow::CONTINUE
             }
         }
-
-        fn visit_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
-            if let ty::PredicateKind::ConstEvaluatable(def, substs) = pred.kind().skip_binder() {
-                // FIXME(const_evaluatable_checked): We should probably deduplicate the logic for
-                // `AbstractConst`s here, it might make sense to change `ConstEvaluatable` to
-                // take a `ty::Const` instead.
-                use rustc_middle::mir::abstract_const::Node;
-                if let Ok(Some(ct)) = AbstractConst::new(self.tcx, def, substs) {
-                    const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
-                        Node::Leaf(leaf) => {
-                            let leaf = leaf.subst(self.tcx, ct.substs);
-                            self.visit_const(leaf)
-                        }
-                        Node::Cast(_, _, ty) => self.visit_ty(ty),
-                        Node::Binop(..) | Node::UnaryOp(..) | Node::FunctionCall(_, _) => {
-                            ControlFlow::CONTINUE
-                        }
-                    })
-                } else {
-                    ControlFlow::CONTINUE
-                }
-            } else {
-                pred.super_visit_with(self)
-            }
-        }
     }
 
     value
index 19e3c1afb9fb6691ed50ff634692b8cf4ff6261c..7038f16a2c9c4032652964b9c2590f284706f675 100644 (file)
@@ -10,6 +10,7 @@
 use super::Selection;
 use super::SelectionContext;
 use super::SelectionError;
+use super::TraitQueryMode;
 use super::{
     ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData,
     ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData,
@@ -18,7 +19,7 @@
 
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::error_reporting::InferCtxtExt as _;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
@@ -362,25 +363,40 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         if !needs_normalization(&ty, self.param_env.reveal()) {
             return ty;
         }
-        // We don't want to normalize associated types that occur inside of region
-        // binders, because they may contain bound regions, and we can't cope with that.
+
+        // We try to be a little clever here as a performance optimization in
+        // cases where there are nested projections under binders.
+        // For example:
+        // ```
+        // for<'a> fn(<T as Foo>::One<'a, Box<dyn Bar<'a, Item=<T as Foo>::Two<'a>>>>)
+        // ```
+        // We normalize the substs on the projection before the projecting, but
+        // if we're naive, we'll
+        //   replace bound vars on inner, project inner, replace placeholders on inner,
+        //   replace bound vars on outer, project outer, replace placeholders on outer
         //
-        // Example:
+        // However, if we're a bit more clever, we can replace the bound vars
+        // on the entire type before normalizing nested projections, meaning we
+        //   replace bound vars on outer, project inner,
+        //   project outer, replace placeholders on outer
         //
-        //     for<'a> fn(<T as Foo<&'a>>::A)
+        // This is possible because the inner `'a` will already be a placeholder
+        // when we need to normalize the inner projection
         //
-        // Instead of normalizing `<T as Foo<&'a>>::A` here, we'll
-        // normalize it when we instantiate those bound regions (which
-        // should occur eventually).
+        // On the other hand, this does add a bit of complexity, since we only
+        // replace bound vars if the current type is a `Projection` and we need
+        // to make sure we don't forget to fold the substs regardless.
 
-        let ty = ty.super_fold_with(self);
         match *ty.kind() {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
-                    Reveal::UserFacing => ty,
+                    Reveal::UserFacing => ty.super_fold_with(self),
 
                     Reveal::All => {
+                        // N.b. there is an assumption here all this code can handle
+                        // escaping bound vars.
+
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
@@ -392,6 +408,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                             self.selcx.infcx().report_overflow_error(&obligation, true);
                         }
 
+                        let substs = substs.super_fold_with(self);
                         let generic_ty = self.tcx().type_of(def_id);
                         let concrete_ty = generic_ty.subst(self.tcx(), substs);
                         self.depth += 1;
@@ -403,18 +420,13 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             }
 
             ty::Projection(data) if !data.has_escaping_bound_vars() => {
-                // This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B: Fn(&'a i32)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
+                // This branch is *mostly* just an optimization: when we don't
+                // have escaping bound vars, we don't need to replace them with
+                // placeholders (see branch below). *Also*, we know that we can
+                // register an obligation to *later* project, since we know
+                // 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,
@@ -433,22 +445,23 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty
             }
 
-            ty::Projection(data) if !data.trait_ref(self.tcx()).has_escaping_bound_vars() => {
-                // Okay, so you thought the previous branch was hacky. Well, to
-                // extend upon this, when the *trait ref* doesn't have escaping
-                // bound vars, but the associated item *does* (can only occur
-                // with GATs), then we might still be able to project the type.
-                // For this, we temporarily replace the bound vars with
-                // placeholders. Note though, that in the case that we still
-                // can't project for whatever reason (e.g. self type isn't
-                // known enough), we *can't* register an obligation and return
-                // an inference variable (since then that obligation would have
-                // bound vars and that's a can of worms). Instead, we just
-                // give up and fall back to pretending like we never tried!
+            ty::Projection(data) => {
+                // If there are escaping bound vars, we temporarily replace the
+                // bound vars with placeholders. Note though, that in the case
+                // that we still can't project for whatever reason (e.g. self
+                // type isn't known enough), we *can't* register an obligation
+                // and return an inference variable (since then that obligation
+                // would have bound vars and that's a can of worms). Instead,
+                // we just give up and fall back to pretending like we never tried!
+                //
+                // Note: this isn't necessarily the final approach here; we may
+                // want to figure out how to register obligations with escaping vars
+                // or handle this some other way.
 
                 let infcx = self.selcx.infcx();
                 let (data, mapped_regions, mapped_types, mapped_consts) =
                     BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
+                let data = data.super_fold_with(self);
                 let normalized_ty = opt_normalize_projection_type(
                     self.selcx,
                     self.param_env,
@@ -459,16 +472,18 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 )
                 .ok()
                 .flatten()
-                .unwrap_or_else(|| ty);
-
-                let normalized_ty = PlaceholderReplacer::replace_placeholders(
-                    infcx,
-                    mapped_regions,
-                    mapped_types,
-                    mapped_consts,
-                    &self.universes,
-                    normalized_ty,
-                );
+                .map(|normalized_ty| {
+                    PlaceholderReplacer::replace_placeholders(
+                        infcx,
+                        mapped_regions,
+                        mapped_types,
+                        mapped_consts,
+                        &self.universes,
+                        normalized_ty,
+                    )
+                })
+                .unwrap_or_else(|| ty.super_fold_with(self));
+
                 debug!(
                     ?self.depth,
                     ?ty,
@@ -479,7 +494,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 normalized_ty
             }
 
-            _ => ty,
+            _ => ty.super_fold_with(self),
         }
     }
 
@@ -898,6 +913,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     }
 
     let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty);
+
     match project_type(selcx, &obligation) {
         Ok(ProjectedTy::Progress(Progress {
             ty: projected_ty,
@@ -908,9 +924,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             // an impl, where-clause etc) and hence we must
             // re-normalize it
 
+            let projected_ty = selcx.infcx().resolve_vars_if_possible(projected_ty);
             debug!(?projected_ty, ?depth, ?projected_obligations);
 
-            let result = if projected_ty.has_projections() {
+            let mut result = if projected_ty.has_projections() {
                 let mut normalizer = AssocTypeNormalizer::new(
                     selcx,
                     param_env,
@@ -927,8 +944,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                 Normalized { value: projected_ty, obligations: projected_obligations }
             };
 
-            let cache_value = prune_cache_value_obligations(infcx, &result);
-            infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, cache_value);
+            let mut canonical =
+                SelectionContext::with_query_mode(selcx.infcx(), TraitQueryMode::Canonical);
+            result.obligations.drain_filter(|projected_obligation| {
+                // If any global obligations always apply, considering regions, then we don't
+                // need to include them. The `is_global` check rules out inference variables,
+                // so there's no need for the caller of `opt_normalize_projection_type`
+                // to evaluate them.
+                // Note that we do *not* discard obligations that evaluate to
+                // `EvaluatedtoOkModuloRegions`. Evaluating these obligations
+                // inside of a query (e.g. `evaluate_obligation`) can change
+                // the result to `EvaluatedToOkModuloRegions`, while an
+                // `EvaluatedToOk` obligation will never change the result.
+                // See #85360 for more details
+                projected_obligation.is_global(canonical.tcx())
+                    && canonical
+                        .evaluate_root_obligation(projected_obligation)
+                        .map_or(false, |res| res.must_apply_considering_regions())
+            });
+
+            infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
             obligations.extend(result.obligations);
             Ok(Some(result.value))
         }
@@ -959,49 +994,6 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     }
 }
 
-/// If there are unresolved type variables, then we need to include
-/// any subobligations that bind them, at least until those type
-/// variables are fully resolved.
-fn prune_cache_value_obligations<'a, 'tcx>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    result: &NormalizedTy<'tcx>,
-) -> NormalizedTy<'tcx> {
-    if infcx.unresolved_type_vars(&result.value).is_none() {
-        return NormalizedTy { value: result.value, obligations: vec![] };
-    }
-
-    let mut obligations: Vec<_> = result
-        .obligations
-        .iter()
-        .filter(|obligation| {
-            let bound_predicate = obligation.predicate.kind();
-            match bound_predicate.skip_binder() {
-                // We found a `T: Foo<X = U>` predicate, let's check
-                // if `U` references any unresolved type
-                // variables. In principle, we only care if this
-                // projection can help resolve any of the type
-                // variables found in `result.value` -- but we just
-                // check for any type variables here, for fear of
-                // indirect obligations (e.g., we project to `?0`,
-                // but we have `T: Foo<X = ?1>` and `?1: Bar<X =
-                // ?0>`).
-                ty::PredicateKind::Projection(data) => {
-                    infcx.unresolved_type_vars(&bound_predicate.rebind(data.ty)).is_some()
-                }
-
-                // We are only interested in `T: Foo<X = U>` predicates, whre
-                // `U` references one of `unresolved_type_vars`. =)
-                _ => false,
-            }
-        })
-        .cloned()
-        .collect();
-
-    obligations.shrink_to_fit();
-
-    NormalizedTy { value: result.value, obligations }
-}
-
 /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
 /// hold. In various error cases, we cannot generate a valid
 /// normalized projection. Therefore, we create an inference variable
index 2dc48e47efccdf6a9e150b8e3e88b844a82422ea..032d402fec0459a6462054fab649ac0ec72be20f 100644 (file)
@@ -71,7 +71,7 @@ fn evaluate_obligation(
         // Run canonical query. If overflow occurs, rerun from scratch but this time
         // in standard trait query mode so that overflow is handled appropriately
         // within `SelectionContext`.
-        self.tcx.evaluate_obligation(c_pred)
+        self.tcx.at(obligation.cause.span(self.tcx)).evaluate_obligation(c_pred)
     }
 
     // Helper function that canonicalizes and runs the query. If an
index 3f6efa03b3a28b27694bab4c2743c857285f10ac..ed5fe466c69f7579afe644b6d5c0e95228493a15 100644 (file)
@@ -14,7 +14,9 @@
 use rustc_middle::mir;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
+
+use std::ops::ControlFlow;
 
 use super::NoSolution;
 
@@ -65,6 +67,27 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             universes: vec![],
         };
 
+        // This is actually a consequence by the way `normalize_erasing_regions` works currently.
+        // Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
+        // through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
+        // with trying to normalize with escaping bound vars.
+        //
+        // Here, we just add the universes that we *would* have created had we passed through the binders.
+        //
+        // We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
+        // The rest of the code is already set up to be lazy about replacing bound vars,
+        // and only when we actually have to normalize.
+        if value.has_escaping_bound_vars() {
+            let mut max_visitor = MaxEscapingBoundVarVisitor {
+                tcx: self.infcx.tcx,
+                outer_index: ty::INNERMOST,
+                escaping: 0,
+            };
+            value.visit_with(&mut max_visitor);
+            if max_visitor.escaping > 0 {
+                normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
+            }
+        }
         let result = value.fold_with(&mut normalizer);
         info!(
             "normalize::<{}>: result={:?} with {} obligations",
@@ -85,6 +108,63 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
     }
 }
 
+/// Visitor to find the maximum escaping bound var
+struct MaxEscapingBoundVarVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    // The index which would count as escaping
+    outer_index: ty::DebruijnIndex,
+    escaping: usize,
+}
+
+impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor<'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
+    fn visit_binder<T: TypeFoldable<'tcx>>(
+        &mut self,
+        t: &ty::Binder<'tcx, T>,
+    ) -> ControlFlow<Self::BreakTy> {
+        self.outer_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.outer_index.shift_out(1);
+        result
+    }
+
+    #[inline]
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if t.outer_exclusive_binder() > self.outer_index {
+            self.escaping = self
+                .escaping
+                .max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
+        }
+        ControlFlow::CONTINUE
+    }
+
+    #[inline]
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match *r {
+            ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => {
+                self.escaping =
+                    self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
+            }
+            _ => {}
+        }
+        ControlFlow::CONTINUE
+    }
+
+    fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
+        match ct.val {
+            ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
+                self.escaping =
+                    self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
+                ControlFlow::CONTINUE
+            }
+            _ => ct.super_visit_with(self),
+        }
+    }
+}
+
 struct QueryNormalizer<'cx, 'tcx> {
     infcx: &'cx InferCtxt<'cx, 'tcx>,
     cause: &'cx ObligationCause<'tcx>,
@@ -121,14 +201,21 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             return ty;
         }
 
-        let ty = ty.super_fold_with(self);
+        // See note in `rustc_trait_selection::traits::project` about why we
+        // wait to fold the substs.
+
+        // Wrap this in a closure so we don't accidentally return from the outer function
         let res = (|| match *ty.kind() {
-            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
+            ty::Opaque(def_id, substs) => {
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal() {
-                    Reveal::UserFacing => ty,
+                    Reveal::UserFacing => ty.super_fold_with(self),
 
                     Reveal::All => {
+                        // N.b. there is an assumption here all this code can handle
+                        // escaping bound vars.
+
+                        let substs = substs.super_fold_with(self);
                         let recursion_limit = self.tcx().recursion_limit();
                         if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
@@ -161,19 +248,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             }
 
             ty::Projection(data) if !data.has_escaping_bound_vars() => {
-                // This is kind of hacky -- we need to be able to
-                // handle normalization within binders because
-                // otherwise we wind up a need to normalize when doing
-                // trait matching (since you can have a trait
-                // obligation like `for<'a> T::B: Fn(&'a i32)`), but
-                // we can't normalize with bound regions in scope. So
-                // far now we just ignore binders but only normalize
-                // if all bound regions are gone (and then we still
-                // have to renormalize whenever we instantiate a
-                // binder). It would be better to normalize in a
-                // binding-aware fashion.
+                // This branch is just an optimization: when we don't have escaping bound vars,
+                // we don't need to replace them with placeholders (see branch below).
 
                 let tcx = self.infcx.tcx;
+                let data = data.super_fold_with(self);
 
                 let mut orig_values = OriginalQueryValues::default();
                 // HACK(matthewjasper) `'static` is special-cased in selection,
@@ -188,7 +267,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                         // We don't expect ambiguity.
                         if result.is_ambiguous() {
                             self.error = true;
-                            return ty;
+                            return ty.super_fold_with(self);
                         }
 
                         match self.infcx.instantiate_query_response_and_region_obligations(
@@ -206,33 +285,20 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
 
                             Err(_) => {
                                 self.error = true;
-                                ty
+                                ty.super_fold_with(self)
                             }
                         }
                     }
 
                     Err(NoSolution) => {
                         self.error = true;
-                        ty
+                        ty.super_fold_with(self)
                     }
                 }
             }
-            ty::Projection(data) if !data.trait_ref(self.infcx.tcx).has_escaping_bound_vars() => {
-                // See note in `rustc_trait_selection::traits::project`
 
-                // One other point mentioning: In `traits::project`, if a
-                // projection can't be normalized, we return an inference variable
-                // and register an obligation to later resolve that. Here, the query
-                // will just return ambiguity. In both cases, the effect is the same: we only want
-                // to return `ty` because there are bound vars that we aren't yet handling in a more
-                // complete way.
-
-                // `BoundVarReplacer` can't handle escaping bound vars. Ideally, we want this before even calling
-                // `QueryNormalizer`, but some const-generics tests pass escaping bound vars.
-                // Also, use `ty` so we get that sweet `outer_exclusive_binder` optimization
-                assert!(!ty.has_vars_bound_at_or_above(ty::DebruijnIndex::from_usize(
-                    self.universes.len()
-                )));
+            ty::Projection(data) => {
+                // See note in `rustc_trait_selection::traits::project`
 
                 let tcx = self.infcx.tcx;
                 let infcx = self.infcx;
@@ -252,12 +318,12 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                     .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
                 debug!("QueryNormalizer: c_data = {:#?}", c_data);
                 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
-                let normalized_ty = match tcx.normalize_projection_ty(c_data) {
+                match tcx.normalize_projection_ty(c_data) {
                     Ok(result) => {
                         // We don't expect ambiguity.
                         if result.is_ambiguous() {
                             self.error = true;
-                            return ty;
+                            return ty.super_fold_with(self);
                         }
                         match self.infcx.instantiate_query_response_and_region_obligations(
                             self.cause,
@@ -269,30 +335,29 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                                 debug!("QueryNormalizer: result = {:#?}", result);
                                 debug!("QueryNormalizer: obligations = {:#?}", obligations);
                                 self.obligations.extend(obligations);
-                                result.normalized_ty
+                                crate::traits::project::PlaceholderReplacer::replace_placeholders(
+                                    infcx,
+                                    mapped_regions,
+                                    mapped_types,
+                                    mapped_consts,
+                                    &self.universes,
+                                    result.normalized_ty,
+                                )
                             }
                             Err(_) => {
                                 self.error = true;
-                                ty
+                                ty.super_fold_with(self)
                             }
                         }
                     }
                     Err(NoSolution) => {
                         self.error = true;
-                        ty
+                        ty.super_fold_with(self)
                     }
-                };
-                crate::traits::project::PlaceholderReplacer::replace_placeholders(
-                    infcx,
-                    mapped_regions,
-                    mapped_types,
-                    mapped_consts,
-                    &self.universes,
-                    normalized_ty,
-                )
+                }
             }
 
-            _ => ty,
+            _ => ty.super_fold_with(self),
         })();
         self.cache.insert(ty, res);
         res
index ba62ce1d5312ebfa5d61b75cb1000b741069d049..6fae8173985be82c233b0ce04dcac77e09b7e55c 100644 (file)
@@ -8,7 +8,6 @@
 //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::Constness;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@@ -75,7 +74,7 @@ pub(super) fn confirm_candidate(
             ProjectionCandidate(idx) => {
                 let obligations = self.confirm_projection_candidate(obligation, idx)?;
                 // FIXME(jschievink): constness
-                Ok(ImplSource::Param(obligations, Constness::NotConst))
+                Ok(ImplSource::Param(obligations, ty::BoundConstness::NotConst))
             }
 
             ObjectCandidate(idx) => {
@@ -113,7 +112,7 @@ pub(super) fn confirm_candidate(
                 // This indicates something like `Trait + Send: Send`. In this case, we know that
                 // this holds because that's what the object type is telling us, and there's really
                 // no additional obligations to prove and no types in particular to unify, etc.
-                Ok(ImplSource::Param(Vec::new(), Constness::NotConst))
+                Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst))
             }
 
             BuiltinUnsizeCandidate => {
@@ -947,7 +946,7 @@ fn confirm_builtin_unsize_candidate(
 
                 let mut unsizing_params = GrowableBitSet::new_empty();
                 if tcx.features().relaxed_struct_unsize {
-                    for arg in tail_field_ty.walk() {
+                    for arg in tail_field_ty.walk(tcx) {
                         if let Some(i) = maybe_unsizing_param_idx(arg) {
                             unsizing_params.insert(i);
                         }
@@ -956,7 +955,7 @@ fn confirm_builtin_unsize_candidate(
                     // Ensure none of the other fields mention the parameters used
                     // in unsizing.
                     for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk() {
+                        for arg in tcx.type_of(field.did).walk(tcx) {
                             if let Some(i) = maybe_unsizing_param_idx(arg) {
                                 unsizing_params.remove(i);
                             }
@@ -968,7 +967,7 @@ fn confirm_builtin_unsize_candidate(
                     }
                 } else {
                     let mut found = false;
-                    for arg in tail_field_ty.walk() {
+                    for arg in tail_field_ty.walk(tcx) {
                         if let Some(i) = maybe_unsizing_param_idx(arg) {
                             unsizing_params.insert(i);
                             found = true;
@@ -984,7 +983,7 @@ fn confirm_builtin_unsize_candidate(
                     // by putting it in a query; it would only need the `DefId` as it
                     // looks at declared field types, not anything substituted.
                     for field in prefix_fields {
-                        for arg in tcx.type_of(field.did).walk() {
+                        for arg in tcx.type_of(field.did).walk(tcx) {
                             if let Some(i) = maybe_unsizing_param_idx(arg) {
                                 if unsizing_params.contains(i) {
                                     return Err(Unimplemented);
index c150b22226627250362328685cfae2d6090fd511..22013fb79cf797d3f68dd9d49a02331ee5e8b331 100644 (file)
@@ -32,7 +32,6 @@
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::Constness;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::abstract_const::NotConstEvaluatable;
@@ -130,8 +129,8 @@ pub struct SelectionContext<'cx, 'tcx> {
     /// and a negative impl
     allow_negative_impls: bool,
 
-    /// Do we only want const impls when we have a const trait predicate?
-    const_impls_required: bool,
+    /// Are we in a const context that needs `~const` bounds to be const?
+    is_in_const_context: bool,
 
     /// The mode that trait queries run in, which informs our error handling
     /// policy. In essence, canonicalized queries need their errors propagated
@@ -224,7 +223,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
-            const_impls_required: false,
+            is_in_const_context: false,
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -236,7 +235,7 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tc
             intercrate: true,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
-            const_impls_required: false,
+            is_in_const_context: false,
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -252,7 +251,7 @@ pub fn with_negative(
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls,
-            const_impls_required: false,
+            is_in_const_context: false,
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -268,7 +267,7 @@ pub fn with_query_mode(
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
-            const_impls_required: false,
+            is_in_const_context: false,
             query_mode,
         }
     }
@@ -283,7 +282,7 @@ pub fn with_constness(
             intercrate: false,
             intercrate_ambiguity_causes: None,
             allow_negative_impls: false,
-            const_impls_required: matches!(constness, hir::Constness::Const),
+            is_in_const_context: matches!(constness, hir::Constness::Const),
             query_mode: TraitQueryMode::Standard,
         }
     }
@@ -316,14 +315,19 @@ pub fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
+    /// Returns `true` if the trait predicate is considerd `const` to this selection context.
+    pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
+        match pred.constness {
+            ty::BoundConstness::ConstIfConst if self.is_in_const_context => true,
+            _ => false,
+        }
+    }
+
     /// Returns `true` if the predicate is considered `const` to
     /// this selection context.
     pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool {
         match pred.kind().skip_binder() {
-            ty::PredicateKind::Trait(ty::TraitPredicate {
-                constness: hir::Constness::Const,
-                ..
-            }) if self.const_impls_required => true,
+            ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred),
             _ => false,
         }
     }
@@ -544,7 +548,7 @@ fn evaluate_predicate_recursively<'o>(
                 },
 
                 ty::PredicateKind::TypeOutlives(pred) => {
-                    if pred.0.is_global() {
+                    if pred.0.is_known_global() {
                         Ok(EvaluatedToOk)
                     } else {
                         Ok(EvaluatedToOkModuloRegions)
@@ -598,11 +602,10 @@ fn evaluate_predicate_recursively<'o>(
                     }
                 }
 
-                ty::PredicateKind::ConstEvaluatable(def_id, substs) => {
+                ty::PredicateKind::ConstEvaluatable(uv) => {
                     match const_evaluatable::is_const_evaluatable(
                         self.infcx,
-                        def_id,
-                        substs,
+                        uv,
                         obligation.param_env,
                         obligation.cause.span,
                     ) {
@@ -616,7 +619,7 @@ fn evaluate_predicate_recursively<'o>(
                 ty::PredicateKind::ConstEquate(c1, c2) => {
                     debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
 
-                    if self.tcx().features().const_evaluatable_checked {
+                    if self.tcx().features().generic_const_exprs {
                         // FIXME: we probably should only try to unify abstract constants
                         // if the constants depend on generic parameters.
                         //
@@ -624,7 +627,7 @@ fn evaluate_predicate_recursively<'o>(
                         if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
                             (c1.val, c2.val)
                         {
-                            if self.infcx.try_unify_abstract_consts(a, b) {
+                            if self.infcx.try_unify_abstract_consts(a.shrink(), b.shrink()) {
                                 return Ok(EvaluatedToOk);
                             }
                         }
@@ -679,7 +682,7 @@ fn evaluate_predicate_recursively<'o>(
             }
         });
 
-        debug!(?result);
+        debug!("finished: {:?} from {:?}", result, obligation);
 
         result
     }
@@ -692,8 +695,12 @@ fn evaluate_trait_predicate_recursively<'o>(
         debug!(?obligation, "evaluate_trait_predicate_recursively");
 
         if !self.intercrate
-            && obligation.is_global()
-            && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
+            && obligation.is_global(self.tcx())
+            && obligation
+                .param_env
+                .caller_bounds()
+                .iter()
+                .all(|bound| bound.definitely_needs_subst(self.tcx()))
         {
             // If a param env has no global bounds, global obligations do not
             // depend on its particular value in order to work, so we can clear
@@ -1071,30 +1078,28 @@ fn filter_impls(
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         let tcx = self.tcx();
         // Respect const trait obligations
-        if self.const_impls_required {
-            if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
-                if Some(obligation.predicate.skip_binder().trait_ref.def_id)
-                    != tcx.lang_items().sized_trait()
-                // const Sized bounds are skipped
-                {
-                    match candidate {
-                        // const impl
-                        ImplCandidate(def_id)
-                            if tcx.impl_constness(def_id) == hir::Constness::Const => {}
-                        // const param
-                        ParamCandidate(ty::ConstnessAnd {
-                            constness: hir::Constness::Const,
-                            ..
-                        }) => {}
-                        // auto trait impl
-                        AutoImplCandidate(..) => {}
-                        // generator, this will raise error in other places
-                        // or ignore error with const_async_blocks feature
-                        GeneratorCandidate => {}
-                        _ => {
-                            // reject all other types of candidates
-                            return Err(Unimplemented);
-                        }
+        if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
+            if Some(obligation.predicate.skip_binder().trait_ref.def_id)
+                != tcx.lang_items().sized_trait()
+            // const Sized bounds are skipped
+            {
+                match candidate {
+                    // const impl
+                    ImplCandidate(def_id)
+                        if tcx.impl_constness(def_id) == hir::Constness::Const => {}
+                    // const param
+                    ParamCandidate(ty::ConstnessAnd {
+                        constness: ty::BoundConstness::ConstIfConst,
+                        ..
+                    }) => {}
+                    // auto trait impl
+                    AutoImplCandidate(..) => {}
+                    // generator, this will raise error in other places
+                    // or ignore error with const_async_blocks feature
+                    GeneratorCandidate => {}
+                    _ => {
+                        // reject all other types of candidates
+                        return Err(Unimplemented);
                     }
                 }
             }
@@ -1452,7 +1457,7 @@ fn candidate_should_be_dropped_in_favor_of(
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
         let is_global =
-            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
+            |cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions();
 
         // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
         // and `DiscriminantKindCandidate` to anything else.
@@ -1492,7 +1497,9 @@ fn candidate_should_be_dropped_in_favor_of(
                     // probably best characterized as a "hack", since we might prefer to just do our
                     // best to *not* create essentially duplicate candidates in the first place.
                     other.value.bound_vars().len() <= victim.value.bound_vars().len()
-                } else if other.value == victim.value && victim.constness == Constness::NotConst {
+                } else if other.value == victim.value
+                    && victim.constness == ty::BoundConstness::NotConst
+                {
                     // Drop otherwise equivalent non-const candidates in favor of const candidates.
                     true
                 } else {
index a6323a65aadbce9c4a451c13fc5049422a34eb9c..ac8bab0cf36a77913ab3c5a5cd57de7e6ac9b478 100644 (file)
@@ -130,6 +130,9 @@ fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
 
 impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
     type BreakTy = NonStructuralMatchTy<'tcx>;
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx())
+    }
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         debug!("Search visiting ty: {:?}", ty);
index fd94f9f799847496580e1d330d1349555a195308..b108d85bb20c9afc2184fab8be73133fc8d05289 100644 (file)
@@ -285,15 +285,10 @@ pub fn upcast_choices(
 /// that come from `trait_ref`, excluding its supertraits. Used in
 /// computing the vtable base for an upcast trait of a trait object.
 pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
-    let mut entries = 0;
-    // Count number of methods and add them to the total offset.
-    // Skip over associated types and constants.
-    for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() {
-        if trait_item.kind == ty::AssocKind::Fn {
-            entries += 1;
-        }
-    }
-    entries
+    let existential_trait_ref =
+        trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+    let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
+    tcx.own_existential_vtable_entries(existential_trait_ref).len()
 }
 
 /// Given an upcast trait object described by `object`, returns the
@@ -304,22 +299,21 @@ pub fn get_vtable_index_of_object_method<N>(
     object: &super::ImplSourceObjectData<'tcx, N>,
     method_def_id: DefId,
 ) -> usize {
+    let existential_trait_ref = object
+        .upcast_trait_ref
+        .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+    let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
     // Count number of methods preceding the one we are selecting and
     // add them to the total offset.
-    // Skip over associated types and constants, as those aren't stored in the vtable.
-    let mut entries = object.vtable_base;
-    for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
-        if trait_item.def_id == method_def_id {
-            // The item with the ID we were given really ought to be a method.
-            assert_eq!(trait_item.kind, ty::AssocKind::Fn);
-            return entries;
-        }
-        if trait_item.kind == ty::AssocKind::Fn {
-            entries += 1;
-        }
-    }
-
-    bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+    let index = tcx
+        .own_existential_vtable_entries(existential_trait_ref)
+        .iter()
+        .copied()
+        .position(|def_id| def_id == method_def_id)
+        .unwrap_or_else(|| {
+            bug!("get_vtable_index_of_object_method: {:?} was not found", method_def_id);
+        });
+    object.vtable_base + index
 }
 
 pub fn closure_trait_ref_and_return_type(
index afef784b4c6cce4986254954e84ec281b2e105ea..75307f135636be8f9be8f425e12f9a4b6c30207e 100644 (file)
@@ -132,8 +132,9 @@ pub fn predicate_obligations<'a, 'tcx>(
             wf.compute(a.into());
             wf.compute(b.into());
         }
-        ty::PredicateKind::ConstEvaluatable(def, substs) => {
-            let obligations = wf.nominal_obligations(def.did, substs);
+        ty::PredicateKind::ConstEvaluatable(uv) => {
+            let substs = uv.substs(wf.tcx());
+            let obligations = wf.nominal_obligations(uv.def.did, substs);
             wf.out.extend(obligations);
 
             for arg in substs.iter() {
@@ -422,7 +423,7 @@ fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<
 
     /// Pushes all the predicates needed to validate that `ty` is WF into `out`.
     fn compute(&mut self, arg: GenericArg<'tcx>) {
-        let mut walker = arg.walk();
+        let mut walker = arg.walk(self.tcx());
         let param_env = self.param_env;
         let depth = self.recursion_depth;
         while let Some(arg) = walker.next() {
@@ -435,14 +436,17 @@ fn compute(&mut self, arg: GenericArg<'tcx>) {
 
                 GenericArgKind::Const(constant) => {
                     match constant.val {
-                        ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
-                            assert!(promoted.is_none());
+                        ty::ConstKind::Unevaluated(uv) => {
+                            assert!(uv.promoted.is_none());
+                            let substs = uv.substs(self.tcx());
 
-                            let obligations = self.nominal_obligations(def.did, substs);
+                            let obligations = self.nominal_obligations(uv.def.did, substs);
                             self.out.extend(obligations);
 
-                            let predicate = ty::PredicateKind::ConstEvaluatable(def, substs)
-                                .to_predicate(self.tcx());
+                            let predicate = ty::PredicateKind::ConstEvaluatable(
+                                ty::Unevaluated::new(uv.def, substs),
+                            )
+                            .to_predicate(self.tcx());
                             let cause = self.cause(traits::MiscObligation);
                             self.out.push(traits::Obligation::with_depth(
                                 cause,
index 330fd497fa1f83eea5105c4cd705dea4ed38626c..1d4196e574782622ef60bedabf932a003acf0ae1 100644 (file)
@@ -806,7 +806,7 @@ fn lower_into(
     tcx: TyCtxt<'tcx>,
     ty: Binder<'tcx, T>,
 ) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) {
-    let mut bound_vars_collector = BoundVarsCollector::new();
+    let mut bound_vars_collector = BoundVarsCollector::new(tcx);
     ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector);
     let mut parameters = bound_vars_collector.parameters;
     let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector
@@ -836,14 +836,16 @@ fn lower_into(
 }
 
 crate struct BoundVarsCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
     binder_index: ty::DebruijnIndex,
     crate parameters: BTreeMap<u32, chalk_ir::VariableKind<RustInterner<'tcx>>>,
     crate named_parameters: Vec<DefId>,
 }
 
 impl<'tcx> BoundVarsCollector<'tcx> {
-    crate fn new() -> Self {
+    crate fn new(tcx: TyCtxt<'tcx>) -> Self {
         BoundVarsCollector {
+            tcx,
             binder_index: ty::INNERMOST,
             parameters: BTreeMap::new(),
             named_parameters: vec![],
@@ -852,6 +854,10 @@ impl<'tcx> BoundVarsCollector<'tcx> {
 }
 
 impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &Binder<'tcx, T>,
@@ -1070,6 +1076,11 @@ impl PlaceholdersCollector {
 }
 
 impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        // Anon const substs do not contain placeholders by default.
+        None
+    }
+
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
             ty::Placeholder(p) if p.universe == self.universe_index => {
index 8dd7c5bdfaebc84183c92f19b35dd218f123ad5e..48c46c3069328e584d86ecca8ad052c54c62526f 100644 (file)
@@ -19,7 +19,7 @@
 mod normalize_projection_ty;
 mod type_op;
 
-pub use type_op::type_op_prove_predicate_with_span;
+pub use type_op::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_span};
 
 use rustc_middle::ty::query::Providers;
 
index c2e0a9987858eac0bb75a3e69f796719d874f4d1..a76fb842616152af6da34f435c8a1b6a4dd69073 100644 (file)
@@ -40,18 +40,28 @@ fn type_op_ascribe_user_type<'tcx>(
     canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
     tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
-        let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts();
-
-        debug!(
-            "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
-            mir_ty, def_id, user_substs
-        );
+        type_op_ascribe_user_type_with_span(infcx, fulfill_cx, key, None)
+    })
+}
 
-        let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
-        cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
+/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
+/// this query can be re-run to better track the span of the obligation cause, and improve the error
+/// message. Do not call directly unless you're in that very specific context.
+pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
+    infcx: &'a InferCtxt<'a, 'tcx>,
+    fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
+    key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
+    span: Option<Span>,
+) -> Result<(), NoSolution> {
+    let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts();
+    debug!(
+        "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
+        mir_ty, def_id, user_substs
+    );
 
-        Ok(())
-    })
+    let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
+    cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs, span)?;
+    Ok(())
 }
 
 struct AscribeUserTypeCx<'me, 'tcx> {
@@ -85,10 +95,15 @@ fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution
         Ok(())
     }
 
-    fn prove_predicate(&mut self, predicate: Predicate<'tcx>) {
+    fn prove_predicate(&mut self, predicate: Predicate<'tcx>, span: Option<Span>) {
+        let cause = if let Some(span) = span {
+            ObligationCause::dummy_with_span(span)
+        } else {
+            ObligationCause::dummy()
+        };
         self.fulfill_cx.register_predicate_obligation(
             self.infcx,
-            Obligation::new(ObligationCause::dummy(), self.param_env, predicate),
+            Obligation::new(cause, self.param_env, predicate),
         );
     }
 
@@ -108,6 +123,7 @@ fn relate_mir_and_user_ty(
         mir_ty: Ty<'tcx>,
         def_id: DefId,
         user_substs: UserSubsts<'tcx>,
+        span: Option<Span>,
     ) -> Result<(), NoSolution> {
         let UserSubsts { user_self_ty, substs } = user_substs;
         let tcx = self.tcx();
@@ -129,7 +145,7 @@ fn relate_mir_and_user_ty(
         debug!(?instantiated_predicates.predicates);
         for instantiated_predicate in instantiated_predicates.predicates {
             let instantiated_predicate = self.normalize(instantiated_predicate);
-            self.prove_predicate(instantiated_predicate);
+            self.prove_predicate(instantiated_predicate, span);
         }
 
         if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
@@ -141,6 +157,7 @@ fn relate_mir_and_user_ty(
 
             self.prove_predicate(
                 ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
+                span,
             );
         }
 
@@ -155,7 +172,10 @@ fn relate_mir_and_user_ty(
         // them?  This would only be relevant if some input
         // type were ill-formed but did not appear in `ty`,
         // which...could happen with normalization...
-        self.prove_predicate(ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()));
+        self.prove_predicate(
+            ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
+            span,
+        );
         Ok(())
     }
 }
index 4c03abb38ca551f466516976ca432c3a0f21e28b..b00d2ab35617f5d8986357ffe9c13d4a9ba545d9 100644 (file)
@@ -54,6 +54,10 @@ fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
 impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
     type BreakTy = ();
 
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        // Anon const substs do not contain bound vars by default.
+        None
+    }
     fn visit_binder<T: TypeFoldable<'tcx>>(
         &mut self,
         t: &Binder<'tcx, T>,
index 8332e7384110e032635faf27466a439ad986f972..27ad7bf4c2d46eae363666ac330ed315791fcfb0 100644 (file)
@@ -223,7 +223,18 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems<'_> {
 }
 
 fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
-    tcx.hir().get_if_local(def_id).and_then(|node| node.ident()).map(|ident| ident.span)
+    tcx.hir()
+        .get_if_local(def_id)
+        .and_then(|node| match node {
+            // A `Ctor` doesn't have an identifier itself, but its parent
+            // struct/variant does. Compare with `hir::Map::opt_span`.
+            hir::Node::Ctor(ctor) => ctor
+                .ctor_hir_id()
+                .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id)))
+                .and_then(|parent| parent.ident()),
+            _ => node.ident(),
+        })
+        .map(|ident| ident.span)
 }
 
 /// If the given `DefId` describes an item belonging to a trait,
@@ -361,7 +372,7 @@ enum NodeKind {
         // constituents are well-formed.
         NodeKind::InherentImpl => {
             let self_ty = tcx.type_of(def_id);
-            inputs.extend(self_ty.walk());
+            inputs.extend(self_ty.walk(tcx));
         }
 
         // In an fn, we assume that the arguments and all their constituents are
@@ -370,7 +381,7 @@ enum NodeKind {
             let fn_sig = tcx.fn_sig(def_id);
             let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
 
-            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
+            inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk(tcx)));
         }
 
         NodeKind::Other => (),
index 2d102127dd9d65dd7c2585590dbe8647e0a60782..c405bbe2d1f53abb2193df1b8a478db40843ced5 100644 (file)
@@ -19,94 +19,116 @@ pub struct TypeFlags: u32 {
         // Does this have parameters? Used to determine whether substitution is
         // required.
         /// Does this have `Param`?
-        const HAS_TY_PARAM                = 1 << 0;
+        const HAS_KNOWN_TY_PARAM                = 1 << 0;
         /// Does this have `ReEarlyBound`?
-        const HAS_RE_PARAM                = 1 << 1;
+        const HAS_KNOWN_RE_PARAM                = 1 << 1;
         /// Does this have `ConstKind::Param`?
-        const HAS_CT_PARAM                = 1 << 2;
+        const HAS_KNOWN_CT_PARAM                = 1 << 2;
 
-        const NEEDS_SUBST                 = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_RE_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits;
+        const KNOWN_NEEDS_SUBST                 = TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_RE_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits;
 
         /// Does this have `Infer`?
-        const HAS_TY_INFER                = 1 << 3;
+        const HAS_TY_INFER                      = 1 << 3;
         /// Does this have `ReVar`?
-        const HAS_RE_INFER                = 1 << 4;
+        const HAS_RE_INFER                      = 1 << 4;
         /// Does this have `ConstKind::Infer`?
-        const HAS_CT_INFER                = 1 << 5;
+        const HAS_CT_INFER                      = 1 << 5;
 
         /// Does this have inference variables? Used to determine whether
         /// inference is required.
-        const NEEDS_INFER                 = TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_RE_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits;
+        const NEEDS_INFER                       = TypeFlags::HAS_TY_INFER.bits
+                                                | TypeFlags::HAS_RE_INFER.bits
+                                                | TypeFlags::HAS_CT_INFER.bits;
 
         /// Does this have `Placeholder`?
-        const HAS_TY_PLACEHOLDER          = 1 << 6;
+        const HAS_TY_PLACEHOLDER                = 1 << 6;
         /// Does this have `RePlaceholder`?
-        const HAS_RE_PLACEHOLDER          = 1 << 7;
+        const HAS_RE_PLACEHOLDER                = 1 << 7;
         /// Does this have `ConstKind::Placeholder`?
-        const HAS_CT_PLACEHOLDER          = 1 << 8;
+        const HAS_CT_PLACEHOLDER                = 1 << 8;
 
         /// `true` if there are "names" of regions and so forth
         /// that are local to a particular fn/inferctxt
-        const HAS_FREE_LOCAL_REGIONS      = 1 << 9;
+        const HAS_KNOWN_FREE_LOCAL_REGIONS      = 1 << 9;
 
         /// `true` if there are "names" of types and regions and so forth
         /// that are local to a particular fn
-        const HAS_FREE_LOCAL_NAMES        = TypeFlags::HAS_TY_PARAM.bits
-                                          | TypeFlags::HAS_CT_PARAM.bits
-                                          | TypeFlags::HAS_TY_INFER.bits
-                                          | TypeFlags::HAS_CT_INFER.bits
-                                          | TypeFlags::HAS_TY_PLACEHOLDER.bits
-                                          | TypeFlags::HAS_CT_PLACEHOLDER.bits
-                                          // We consider 'freshened' types and constants
-                                          // to depend on a particular fn.
-                                          // The freshening process throws away information,
-                                          // which can make things unsuitable for use in a global
-                                          // cache. Note that there is no 'fresh lifetime' flag -
-                                          // freshening replaces all lifetimes with `ReErased`,
-                                          // which is different from how types/const are freshened.
-                                          | TypeFlags::HAS_TY_FRESH.bits
-                                          | TypeFlags::HAS_CT_FRESH.bits
-                                          | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
+        const HAS_KNOWN_FREE_LOCAL_NAMES        = TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits
+                                                | TypeFlags::HAS_TY_INFER.bits
+                                                | TypeFlags::HAS_CT_INFER.bits
+                                                | TypeFlags::HAS_TY_PLACEHOLDER.bits
+                                                | TypeFlags::HAS_CT_PLACEHOLDER.bits
+                                                // We consider 'freshened' types and constants
+                                                // to depend on a particular fn.
+                                                // The freshening process throws away information,
+                                                // which can make things unsuitable for use in a global
+                                                // cache. Note that there is no 'fresh lifetime' flag -
+                                                // freshening replaces all lifetimes with `ReErased`,
+                                                // which is different from how types/const are freshened.
+                                                | TypeFlags::HAS_TY_FRESH.bits
+                                                | TypeFlags::HAS_CT_FRESH.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits;
+
+        const HAS_POTENTIAL_FREE_LOCAL_NAMES    = TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES.bits
+                                                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
 
         /// Does this have `Projection`?
-        const HAS_TY_PROJECTION           = 1 << 10;
+        const HAS_TY_PROJECTION                 = 1 << 10;
         /// Does this have `Opaque`?
-        const HAS_TY_OPAQUE               = 1 << 11;
+        const HAS_TY_OPAQUE                     = 1 << 11;
         /// Does this have `ConstKind::Unevaluated`?
-        const HAS_CT_PROJECTION           = 1 << 12;
+        const HAS_CT_PROJECTION                 = 1 << 12;
 
         /// Could this type be normalized further?
-        const HAS_PROJECTION              = TypeFlags::HAS_TY_PROJECTION.bits
-                                          | TypeFlags::HAS_TY_OPAQUE.bits
-                                          | TypeFlags::HAS_CT_PROJECTION.bits;
+        const HAS_PROJECTION                    = TypeFlags::HAS_TY_PROJECTION.bits
+                                                | TypeFlags::HAS_TY_OPAQUE.bits
+                                                | TypeFlags::HAS_CT_PROJECTION.bits;
 
         /// Is an error type/const reachable?
-        const HAS_ERROR                   = 1 << 13;
+        const HAS_ERROR                         = 1 << 13;
 
         /// Does this have any region that "appears free" in the type?
         /// Basically anything but `ReLateBound` and `ReErased`.
-        const HAS_FREE_REGIONS            = 1 << 14;
+        const HAS_KNOWN_FREE_REGIONS            = 1 << 14;
+
+        const HAS_POTENTIAL_FREE_REGIONS        = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits
+                                                | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
 
         /// Does this have any `ReLateBound` regions? Used to check
         /// if a global bound is safe to evaluate.
-        const HAS_RE_LATE_BOUND           = 1 << 15;
+        const HAS_RE_LATE_BOUND                 = 1 << 15;
 
         /// Does this have any `ReErased` regions?
-        const HAS_RE_ERASED               = 1 << 16;
+        const HAS_RE_ERASED                     = 1 << 16;
 
         /// Does this value have parameters/placeholders/inference variables which could be
         /// replaced later, in a way that would change the results of `impl` specialization?
-        const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
+        ///
+        /// Note that this flag being set is not a guarantee, as it is also
+        /// set if there are any anon consts with unknown default substs.
+        const STILL_FURTHER_SPECIALIZABLE       = 1 << 17;
 
         /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
-        const HAS_TY_FRESH                = 1 << 18;
+        const HAS_TY_FRESH                      = 1 << 18;
 
         /// Does this value have `InferConst::Fresh`?
-        const HAS_CT_FRESH                = 1 << 19;
+        const HAS_CT_FRESH                      = 1 << 19;
+
+        /// Does this value have unknown default anon const substs.
+        ///
+        /// For more details refer to...
+        /// FIXME(@lcnr): ask me for now, still have to write all of this.
+        const HAS_UNKNOWN_DEFAULT_CONST_SUBSTS  = 1 << 20;
+        /// Flags which can be influenced by default anon const substs.
+        const MAY_NEED_DEFAULT_CONST_SUBSTS     = TypeFlags::HAS_KNOWN_RE_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_TY_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_CT_PARAM.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits
+                                                | TypeFlags::HAS_KNOWN_FREE_REGIONS.bits;
+
     }
 }
 
index fa5ef63f5c52e346c1ee99d7bdbee2d3807c4449..dd76a5e4b99b235b0ba395fa38e95776b3029f3e 100644 (file)
@@ -26,3 +26,4 @@ rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
+rustc_lint = { path = "../rustc_lint" }
index 7d7d69b40798f8424866f1747da5db9bb3804316..059e0cadd190cf649cf092fe4a291e48e6ebca11 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{Constness, GenericArg, GenericArgs};
+use rustc_hir::{GenericArg, GenericArgs};
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::GenericParamDefKind;
 use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
@@ -47,8 +47,6 @@ pub trait AstConv<'tcx> {
 
     fn item_def_id(&self) -> Option<DefId>;
 
-    fn default_constness_for_trait_bounds(&self) -> Constness;
-
     /// Returns predicates in scope of the form `X: Foo<T>`, where `X`
     /// is a type parameter `X` with the given id `def_id` and T
     /// matches `assoc_name`. This is a subset of the full set of
@@ -394,7 +392,7 @@ fn default_needs_object_self(&mut self, param: &ty::GenericParamDef) -> bool {
                     if self.is_object && has_default {
                         let default_ty = tcx.at(self.span).type_of(param.def_id);
                         let self_param = tcx.types.self_param;
-                        if default_ty.walk().any(|arg| arg == self_param.into()) {
+                        if default_ty.walk(tcx).any(|arg| arg == self_param.into()) {
                             // There is no suitable inference default for a type parameter
                             // that references self, in an object type.
                             return true;
@@ -724,7 +722,7 @@ pub fn instantiate_poly_trait_ref(
         &self,
         trait_ref: &hir::TraitRef<'_>,
         span: Span,
-        constness: Constness,
+        constness: ty::BoundConstness,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
@@ -795,7 +793,7 @@ pub fn instantiate_lang_item_trait_ref(
         let bound_vars = tcx.late_bound_vars(hir_id);
         let poly_trait_ref =
             ty::Binder::bind_with_vars(ty::TraitRef::new(trait_def_id, substs), bound_vars);
-        bounds.trait_bounds.push((poly_trait_ref, span, Constness::NotConst));
+        bounds.trait_bounds.push((poly_trait_ref, span, ty::BoundConstness::NotConst));
 
         let mut dup_bindings = FxHashMap::default();
         for binding in assoc_bindings {
@@ -920,14 +918,13 @@ fn add_bounds(
         bounds: &mut Bounds<'tcx>,
         bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
     ) {
-        let constness = self.default_constness_for_trait_bounds();
         for ast_bound in ast_bounds {
             match *ast_bound {
                 hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => {
                     self.instantiate_poly_trait_ref(
                         &b.trait_ref,
                         b.span,
-                        constness,
+                        ty::BoundConstness::NotConst,
                         param_ty,
                         bounds,
                         false,
@@ -937,7 +934,7 @@ fn add_bounds(
                     self.instantiate_poly_trait_ref(
                         &b.trait_ref,
                         b.span,
-                        Constness::NotConst,
+                        ty::BoundConstness::ConstIfConst,
                         param_ty,
                         bounds,
                         false,
@@ -1251,7 +1248,7 @@ fn conv_object_ty_poly_trait_ref(
             } = self.instantiate_poly_trait_ref(
                 &trait_bound.trait_ref,
                 trait_bound.span,
-                Constness::NotConst,
+                ty::BoundConstness::NotConst,
                 dummy_self,
                 &mut bounds,
                 false,
@@ -1330,7 +1327,7 @@ trait here instead: `trait NewTrait: {} {{}}`",
             .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id()));
 
         for (base_trait_ref, span, constness) in regular_traits_refs_spans {
-            assert_eq!(constness, Constness::NotConst);
+            assert_eq!(constness, ty::BoundConstness::NotConst);
 
             for obligation in traits::elaborate_trait_ref(tcx, base_trait_ref) {
                 debug!(
@@ -1354,7 +1351,7 @@ trait here instead: `trait NewTrait: {} {{}}`",
                         // A `Self` within the original bound will be substituted with a
                         // `trait_object_dummy_self`, so check for that.
                         let references_self =
-                            pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
+                            pred.skip_binder().ty.walk(tcx).any(|arg| arg == dummy_self.into());
 
                         // If the projection output contains `Self`, force the user to
                         // elaborate it explicitly to avoid a lot of complexity.
@@ -2204,7 +2201,7 @@ pub fn res_to_ty(
                 self.prohibit_generics(path.segments);
                 // Try to evaluate any array length constants.
                 let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
-                if forbid_generic && normalized_ty.needs_subst() {
+                if forbid_generic && normalized_ty.definitely_needs_subst(tcx) {
                     let mut err = tcx.sess.struct_span_err(
                         path.span,
                         "generic `Self` types are currently not permitted in anonymous constants",
@@ -2380,12 +2377,10 @@ fn impl_trait_ty_to_ty(
             if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
                 // Our own parameters are the resolved lifetimes.
                 match param.kind {
-                    GenericParamDefKind::Lifetime => {
-                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
-                            self.ast_region_to_region(lifetime, None).into()
-                        } else {
-                            bug!()
-                        }
+                    GenericParamDefKind::Lifetime
+                        if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] =>
+                    {
+                        self.ast_region_to_region(lifetime, None).into()
                     }
                     _ => bug!(),
                 }
index 5d2006407226304530509df458aa6819b374beb8..24474e163b9daf23586c3d24e2efb063f652c596 100644 (file)
@@ -1,7 +1,6 @@
 //! Bounds are restrictions applied to some types after they've been converted into the
 //! `ty` form from the HIR.
 
-use rustc_hir::Constness;
 use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_span::Span;
 
@@ -30,7 +29,7 @@ pub struct Bounds<'tcx> {
 
     /// A list of trait bounds. So if you had `T: Debug` this would be
     /// `T: Debug`. Note that the self-type is explicit here.
-    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>,
+    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>,
 
     /// A list of projection equality bounds. So if you had `T:
     /// Iterator<Item = u32>` this would include `<T as
index 87fd8f1e03bb3b136e48a126dfc15154b6c77afb..01227cad334fc783e12d0f79ef97b63a5150ae32 100644 (file)
@@ -14,6 +14,7 @@
 };
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+    #[instrument(skip(self), level = "debug")]
     pub fn check_match(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
@@ -26,6 +27,7 @@ pub fn check_match(
 
         let acrb = arms_contain_ref_bindings(arms);
         let scrutinee_ty = self.demand_scrutinee_type(scrut, acrb, arms.is_empty());
+        debug!(?scrutinee_ty);
 
         // If there are no arms, that is a diverging match; a special case.
         if arms.is_empty() {
index 181972e3e7bade679d581f9d78135f6b3e1b4bfb..14550690e63e01e542cfab488bb84b2f480d1679 100644 (file)
@@ -51,6 +51,7 @@
 
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
+#[derive(Debug)]
 pub struct CastCheck<'tcx> {
     expr: &'tcx hir::Expr<'tcx>,
     expr_ty: Ty<'tcx>,
@@ -603,12 +604,11 @@ fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
         });
     }
 
+    #[instrument(skip(fcx), level = "debug")]
     pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
         self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
 
-        debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
-
         if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) {
             self.report_cast_to_unsized_type(fcx);
         } else if self.expr_ty.references_error() || self.cast_ty.references_error() {
index a7fd20888428feaa848b7c8693a6ee8fdf63fdb1..3c9d5b4def4e7a83a67655167919346a98b78eb7 100644 (file)
@@ -470,14 +470,17 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
     debug!(?item, ?span);
 
     struct FoundParentLifetime;
-    struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics);
+    struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
     impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
         type BreakTy = FoundParentLifetime;
+        fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+            Some(self.0)
+        }
 
         fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
             debug!("FindParentLifetimeVisitor: r={:?}", r);
             if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
-                if *index < self.0.parent_count as u32 {
+                if *index < self.1.parent_count as u32 {
                     return ControlFlow::Break(FoundParentLifetime);
                 } else {
                     return ControlFlow::CONTINUE;
@@ -499,21 +502,24 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
     }
 
     struct ProhibitOpaqueVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
         opaque_identity_ty: Ty<'tcx>,
         generics: &'tcx ty::Generics,
-        tcx: TyCtxt<'tcx>,
         selftys: Vec<(Span, Option<String>)>,
     }
 
     impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
         type BreakTy = Ty<'tcx>;
+        fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+            Some(self.tcx)
+        }
 
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
             if t == self.opaque_identity_ty {
                 ControlFlow::CONTINUE
             } else {
-                t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics))
+                t.super_visit_with(&mut FindParentLifetimeVisitor(self.tcx, self.generics))
                     .map_break(|FoundParentLifetime| t)
             }
         }
@@ -1476,7 +1482,7 @@ pub(super) fn check_type_params_are_used<'tcx>(
         return;
     }
 
-    for leaf in ty.walk() {
+    for leaf in ty.walk(tcx) {
         if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
             if let ty::Param(param) = leaf_ty.kind() {
                 debug!("found use of ty param {:?}", param);
@@ -1578,8 +1584,12 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
                 .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
                 .filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
             {
-                struct VisitTypes(Vec<DefId>);
-                impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
+                struct OpaqueTypeCollector(Vec<DefId>);
+                impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector {
+                    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                        // Default anon const substs cannot contain opaque types.
+                        None
+                    }
                     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         match *t.kind() {
                             ty::Opaque(def, _) => {
@@ -1590,7 +1600,7 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                         }
                     }
                 }
-                let mut visitor = VisitTypes(vec![]);
+                let mut visitor = OpaqueTypeCollector(vec![]);
                 ty.visit_with(&mut visitor);
                 for def_id in visitor.0 {
                     let ty_span = tcx.def_span(def_id);
index 0b4df8e6d3cdd5d55bef2c4f4ebfcaf9cd14342b..3bfab9d513f375e6540a3f7471f3c3342d172485 100644 (file)
@@ -796,6 +796,8 @@ fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         //! into a closure or a `proc`.
 
         let b = self.shallow_resolve(b);
+        let InferOk { value: b, mut obligations } =
+            self.normalize_associated_types_in_as_infer_ok(self.cause.span, b);
         debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b);
 
         match b.kind() {
@@ -815,8 +817,9 @@ fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
                     }
                 }
 
-                let InferOk { value: a_sig, mut obligations } =
+                let InferOk { value: a_sig, obligations: o1 } =
                     self.normalize_associated_types_in_as_infer_ok(self.cause.span, a_sig);
+                obligations.extend(o1);
 
                 let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
                 let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
@@ -1328,6 +1331,7 @@ pub fn coerce_forced_unit<'a>(
     /// The inner coercion "engine". If `expression` is `None`, this
     /// is a forced-unit case, and hence `expression_ty` must be
     /// `Nil`.
+    #[instrument(skip(self, fcx, augment_error, label_expression_as_expected), level = "debug")]
     crate fn coerce_inner<'a>(
         &mut self,
         fcx: &FnCtxt<'a, 'tcx>,
index 8d5bf98be9932b177037d98158f2376f12618a4c..d59291b8fd493e1a1c2106e7c629585ac3ff167a 100644 (file)
@@ -250,6 +250,8 @@ fn compare_predicate_entailment<'tcx>(
         // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
+        let mut wf_tys = vec![];
+
         let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
             infer::HigherRankedType,
@@ -260,10 +262,18 @@ fn compare_predicate_entailment<'tcx>(
         let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
         debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
+        // First liberate late bound regions and subst placeholders
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
         let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
+        // Next, add all inputs and output as well-formed tys. Importantly,
+        // we have to do this before normalization, since the normalized ty may
+        // not contain the input parameters. See issue #87748.
+        wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
+        // Also add the resulting inputs and output as well-formed.
+        // This probably isn't strictly necessary.
+        wf_tys.extend(trait_sig.inputs_and_output.iter());
         let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
@@ -388,7 +398,7 @@ fn compare_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
-        fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output);
+        fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys);
 
         Ok(())
     })
@@ -1225,6 +1235,7 @@ fn compare_type_predicate_entailment<'tcx>(
 /// For default associated types the normalization is not possible (the value
 /// from the impl could be overridden). We also can't normalize generic
 /// associated types (yet) because they contain bound parameters.
+#[tracing::instrument(level = "debug", skip(tcx))]
 pub fn check_type_bounds<'tcx>(
     tcx: TyCtxt<'tcx>,
     trait_ty: &ty::AssocItem,
@@ -1238,10 +1249,83 @@ pub fn check_type_bounds<'tcx>(
     //     type Bar<C> =...
     // }
     //
-    // - `impl_substs` would be `[A, B, C]`
-    // - `rebased_substs` would be `[(A, B), u32, C]`, combining the substs from
-    //    the *trait* with the generic associated type parameters.
-    let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
+    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
+    // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
+    // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
+    //    the *trait* with the generic associated type parameters (as bound vars).
+    //
+    // A note regarding the use of bound vars here:
+    // Imagine as an example
+    // ```
+    // trait Family {
+    //     type Member<C: Eq>;
+    // }
+    //
+    // impl Family for VecFamily {
+    //     type Member<C: Eq> = i32;
+    // }
+    // ```
+    // Here, we would generate
+    // ```notrust
+    // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) }
+    // ```
+    // when we really would like to generate
+    // ```notrust
+    // forall<C> { Normalize(<VecFamily as Family>::Member<C> => i32) :- Implemented(C: Eq) }
+    // ```
+    // But, this is probably fine, because although the first clause can be used with types C that
+    // do not implement Eq, for it to cause some kind of problem, there would have to be a
+    // VecFamily::Member<X> for some type X where !(X: Eq), that appears in the value of type
+    // Member<C: Eq> = .... That type would fail a well-formedness check that we ought to be doing
+    // elsewhere, which would check that any <T as Family>::Member<X> meets the bounds declared in
+    // the trait (notably, that X: Eq and T: Family).
+    let defs: &ty::Generics = tcx.generics_of(impl_ty.def_id);
+    let mut substs = smallvec::SmallVec::with_capacity(defs.count());
+    if let Some(def_id) = defs.parent {
+        let parent_defs = tcx.generics_of(def_id);
+        InternalSubsts::fill_item(&mut substs, tcx, parent_defs, &mut |param, _| {
+            tcx.mk_param_from_def(param)
+        });
+    }
+    let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
+        smallvec::SmallVec::with_capacity(defs.count());
+    InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param.kind {
+        GenericParamDefKind::Type { .. } => {
+            let kind = ty::BoundTyKind::Param(param.name);
+            let bound_var = ty::BoundVariableKind::Ty(kind);
+            bound_vars.push(bound_var);
+            tcx.mk_ty(ty::Bound(
+                ty::INNERMOST,
+                ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+            ))
+            .into()
+        }
+        GenericParamDefKind::Lifetime => {
+            let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+            let bound_var = ty::BoundVariableKind::Region(kind);
+            bound_vars.push(bound_var);
+            tcx.mk_region(ty::ReLateBound(
+                ty::INNERMOST,
+                ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
+            ))
+            .into()
+        }
+        GenericParamDefKind::Const { .. } => {
+            let bound_var = ty::BoundVariableKind::Const;
+            bound_vars.push(bound_var);
+            tcx.mk_const(ty::Const {
+                ty: tcx.type_of(param.def_id),
+                val: ty::ConstKind::Bound(
+                    ty::INNERMOST,
+                    ty::BoundVar::from_usize(bound_vars.len() - 1),
+                ),
+            })
+            .into()
+        }
+    });
+    let bound_vars = tcx.mk_bound_variable_kinds(bound_vars.into_iter());
+    let impl_ty_substs = tcx.intern_substs(&substs);
+
     let rebased_substs =
         impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
     let impl_ty_value = tcx.type_of(impl_ty.def_id);
@@ -1270,18 +1354,26 @@ pub fn check_type_bounds<'tcx>(
                 // impl<T> X for T where T: X { type Y = <T as X>::Y; }
             }
             _ => predicates.push(
-                ty::Binder::dummy(ty::ProjectionPredicate {
-                    projection_ty: ty::ProjectionTy {
-                        item_def_id: trait_ty.def_id,
-                        substs: rebased_substs,
+                ty::Binder::bind_with_vars(
+                    ty::ProjectionPredicate {
+                        projection_ty: ty::ProjectionTy {
+                            item_def_id: trait_ty.def_id,
+                            substs: rebased_substs,
+                        },
+                        ty: impl_ty_value,
                     },
-                    ty: impl_ty_value,
-                })
+                    bound_vars,
+                )
                 .to_predicate(tcx),
             ),
         };
         ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing)
     };
+    debug!(?normalize_param_env);
+
+    let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
+    let rebased_substs =
+        impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
         let constness = impl_ty
@@ -1308,6 +1400,7 @@ pub fn check_type_bounds<'tcx>(
             .explicit_item_bounds(trait_ty.def_id)
             .iter()
             .map(|&(bound, span)| {
+                debug!(?bound);
                 let concrete_ty_bound = bound.subst(tcx, rebased_substs);
                 debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
 
index c34dd705bef7b148c25737d6abc8251c752f2ec4..fd150978f0074d8a5c4aea01e80090906b03221a 100644 (file)
@@ -236,9 +236,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
                     relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
                 }
                 (
-                    ty::PredicateKind::ConstEvaluatable(def_a, substs_a),
-                    ty::PredicateKind::ConstEvaluatable(def_b, substs_b),
-                ) => tcx.try_unify_abstract_consts(((def_a, substs_a), (def_b, substs_b))),
+                    ty::PredicateKind::ConstEvaluatable(a),
+                    ty::PredicateKind::ConstEvaluatable(b),
+                ) => tcx.try_unify_abstract_consts((a, b)),
                 (ty::PredicateKind::TypeOutlives(a), ty::PredicateKind::TypeOutlives(b)) => {
                     relator.relate(predicate.rebind(a.0), p.rebind(b.0)).is_ok()
                 }
index 9cbd3f7bb33a3f9f0b1987e90a89e24c0c80aae6..64594a82ec0b6e5dd0838a1e492a81175d205e97 100644 (file)
@@ -156,12 +156,27 @@ pub(super) fn check_expr_with_needs(
     /// Note that inspecting a type's structure *directly* may expose the fact
     /// that there are actually multiple representations for `Error`, so avoid
     /// that when err needs to be handled differently.
+    #[instrument(skip(self), level = "debug")]
     pub(super) fn check_expr_with_expectation(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        debug!(">> type-checking: expected={:?}, expr={:?} ", expected, expr);
+        if self.tcx().sess.verbose() {
+            // make this code only run with -Zverbose because it is probably slow
+            if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                if !lint_str.contains('\n') {
+                    debug!("expr text: {}", lint_str);
+                } else {
+                    let mut lines = lint_str.lines();
+                    if let Some(line0) = lines.next() {
+                        let remaining_lines = lines.count();
+                        debug!("expr text: {}", line0);
+                        debug!("expr text: ...(and {} more lines)", remaining_lines);
+                    }
+                }
+            }
+        }
 
         // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block
         // without the final expr (e.g. `try { return; }`). We don't want to generate an
@@ -834,7 +849,26 @@ fn check_then_else(
         coerce.coerce(self, &self.misc(sp), then_expr, then_ty);
 
         if let Some(else_expr) = opt_else_expr {
-            let else_ty = self.check_expr_with_expectation(else_expr, expected);
+            let else_ty = if sp.desugaring_kind() == Some(DesugaringKind::LetElse) {
+                // todo introduce `check_expr_with_expectation(.., Expectation::LetElse)`
+                //   for errors that point to the offending expression rather than the entire block.
+                //   We could use `check_expr_eq_type(.., tcx.types.never)`, but then there is no
+                //   way to detect that the expected type originated from let-else and provide
+                //   a customized error.
+                let else_ty = self.check_expr(else_expr);
+                let cause = self.cause(else_expr.span, ObligationCauseCode::LetElse);
+
+                if let Some(mut err) =
+                    self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
+                {
+                    err.emit();
+                    self.tcx.ty_error()
+                } else {
+                    else_ty
+                }
+            } else {
+                self.check_expr_with_expectation(else_expr, expected)
+            };
             let else_diverges = self.diverges.get();
 
             let opt_suggest_box_span =
@@ -904,9 +938,10 @@ fn check_expr_assign(
                 );
             }
 
-            if self.sess().if_let_suggestions.borrow().get(&expr.span).is_some() {
-                // We already emitted an `if let` suggestion due to an identifier not found.
-                err.delay_as_bug();
+            // If the assignment expression itself is ill-formed, don't
+            // bother emitting another error
+            if lhs_ty.references_error() || rhs_ty.references_error() {
+                err.delay_as_bug()
             } else {
                 err.emit();
             }
@@ -1039,7 +1074,7 @@ fn check_expr_cast(
         let t_cast = self.to_ty_saving_user_provided_ty(t);
         let t_cast = self.resolve_vars_if_possible(t_cast);
         let t_expr = self.check_expr_with_expectation(e, ExpectCastableToType(t_cast));
-        let t_cast = self.resolve_vars_if_possible(t_cast);
+        let t_expr = self.resolve_vars_if_possible(t_expr);
 
         // Eagerly check for some obvious errors.
         if t_expr.references_error() || t_cast.references_error() {
@@ -1049,6 +1084,10 @@ fn check_expr_cast(
             let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
             match cast::CastCheck::new(self, e, t_expr, t_cast, t.span, expr.span) {
                 Ok(cast_check) => {
+                    debug!(
+                        "check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
+                        t_cast, t_expr, cast_check,
+                    );
                     deferred_cast_checks.push(cast_check);
                     t_cast
                 }
@@ -2145,14 +2184,11 @@ fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
                 hir::InlineAsmOperand::In { expr, .. } => {
                     self.check_expr_asm_operand(expr, true);
                 }
-                hir::InlineAsmOperand::Out { expr, .. } => {
-                    if let Some(expr) = expr {
-                        self.check_expr_asm_operand(expr, false);
-                    }
-                }
-                hir::InlineAsmOperand::InOut { expr, .. } => {
+                hir::InlineAsmOperand::Out { expr: Some(expr), .. }
+                | hir::InlineAsmOperand::InOut { expr, .. } => {
                     self.check_expr_asm_operand(expr, false);
                 }
+                hir::InlineAsmOperand::Out { expr: None, .. } => {}
                 hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                     self.check_expr_asm_operand(in_expr, true);
                     if let Some(out_expr) = out_expr {
index 69a8970ae094e8c4cdca183a83eb0fe7e08677f8..8f6cdc7bb12a7243ab97820e956a4e185c43330d 100644 (file)
@@ -3,7 +3,9 @@
 use rustc_middle::ty::{self, Ty};
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
-    pub(super) fn type_inference_fallback(&self) {
+    /// Performs type inference fallback, returning true if any fallback
+    /// occurs.
+    pub(super) fn type_inference_fallback(&self) -> bool {
         // All type checking constraints were added, try to fallback unsolved variables.
         self.select_obligations_where_possible(false, |_| {});
         let mut fallback_has_occurred = false;
@@ -50,6 +52,8 @@ pub(super) fn type_inference_fallback(&self) {
 
         // See if we can make any more progress.
         self.select_obligations_where_possible(fallback_has_occurred, |_| {});
+
+        fallback_has_occurred
     }
 
     // Tries to apply a fallback to `ty` if it is an unsolved variable.
index f9b7bb8ea9915c0138c8724b47d01f478eb8a0b1..9748c0835bf12e29c4e6463208899f8f4cfe2fd9 100644 (file)
@@ -239,7 +239,7 @@ pub fn write_user_type_annotation_from_substs(
             self.tag(),
         );
 
-        if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
+        if self.can_contain_user_lifetime_bounds((substs, user_self_ty)) {
             let canonicalized = self.infcx.canonicalize_user_type_annotation(UserType::TypeOf(
                 def_id,
                 UserSubsts { substs, user_self_ty },
@@ -481,7 +481,7 @@ pub fn to_ty_saving_user_provided_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
         let ty = self.to_ty(ast_ty);
         debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
 
-        if Self::can_contain_user_lifetime_bounds(ty) {
+        if self.can_contain_user_lifetime_bounds(ty) {
             let c_ty = self.infcx.canonicalize_response(UserType::Ty(ty));
             debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
             self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
@@ -526,11 +526,11 @@ pub fn const_arg_to_const(
     // reader, although I have my doubts). Also pass in types with inference
     // types, because they may be repeated. Other sorts of things are already
     // sufficiently enforced with erased regions. =)
-    fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
+    fn can_contain_user_lifetime_bounds<T>(&self, t: T) -> bool
     where
         T: TypeFoldable<'tcx>,
     {
-        t.has_free_regions() || t.has_projections() || t.has_infer_types()
+        t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types()
     }
 
     pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
@@ -858,13 +858,25 @@ pub fn resolve_ty_and_res_fully_qualified_call(
                     path.segments,
                 );
             }
-            QPath::TypeRelative(ref qself, ref segment) => (self.to_ty(qself), qself, segment),
+            QPath::TypeRelative(ref qself, ref segment) => {
+                // Don't use `self.to_ty`, since this will register a WF obligation.
+                // If we're trying to call a non-existent method on a trait
+                // (e.g. `MyTrait::missing_method`), then resolution will
+                // give us a `QPath::TypeRelative` with a trait object as
+                // `qself`. In that case, we want to avoid registering a WF obligation
+                // for `dyn MyTrait`, since we don't actually need the trait
+                // to be object-safe.
+                // We manually call `register_wf_obligation` in the success path
+                // below.
+                (<dyn AstConv<'_>>::ast_ty_to_ty(self, qself), qself, segment)
+            }
             QPath::LangItem(..) => {
                 bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
             }
         };
         if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
         {
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
             // Return directly on cache hit. This is useful to avoid doubly reporting
             // errors with default match binding modes. See #44614.
             let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
@@ -878,6 +890,14 @@ pub fn resolve_ty_and_res_fully_qualified_call(
                     method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
                     _ => Err(ErrorReported),
                 };
+
+                // If we have a path like `MyTrait::missing_method`, then don't register
+                // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
+                // register a WF obligation so that we can detect any additional
+                // errors in the self type.
+                if !(matches!(error, method::MethodError::NoMatch(_)) && ty.is_trait()) {
+                    self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
+                }
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
@@ -894,7 +914,8 @@ pub fn resolve_ty_and_res_fully_qualified_call(
             });
 
         if result.is_ok() {
-            self.maybe_lint_bare_trait(qpath, hir_id);
+            self.maybe_lint_bare_trait(qpath, hir_id, span);
+            self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None));
         }
 
         // Write back the new resolution.
@@ -906,7 +927,7 @@ pub fn resolve_ty_and_res_fully_qualified_call(
         )
     }
 
-    fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) {
+    fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Span) {
         if let QPath::TypeRelative(self_ty, _) = qpath {
             if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
                 self_ty.kind
@@ -914,12 +935,17 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) {
                 let msg = "trait objects without an explicit `dyn` are deprecated";
                 let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span) {
                     Ok(s) if poly_trait_ref.trait_ref.path.is_global() => {
-                        (format!("<dyn ({})>", s), Applicability::MachineApplicable)
+                        (format!("dyn ({})", s), Applicability::MachineApplicable)
                     }
-                    Ok(s) => (format!("<dyn {}>", s), Applicability::MachineApplicable),
-                    Err(_) => ("<dyn <type>>".to_string(), Applicability::HasPlaceholders),
+                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
+                    Err(_) => ("dyn <type>".to_string(), Applicability::HasPlaceholders),
                 };
-                let replace = String::from("use `dyn`");
+                // Wrap in `<..>` if it isn't already.
+                let sugg = match self.tcx.sess.source_map().span_to_snippet(span) {
+                    Ok(s) if s.starts_with('<') => sugg,
+                    _ => format!("<{}>", sugg),
+                };
+                let sugg_label = "use `dyn`";
                 if self.sess().edition() >= Edition::Edition2021 {
                     let mut err = rustc_errors::struct_span_err!(
                         self.sess(),
@@ -930,8 +956,8 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) {
                     );
                     err.span_suggestion(
                         self_ty.span,
-                        &sugg,
-                        replace,
+                        sugg_label,
+                        sugg,
                         Applicability::MachineApplicable,
                     )
                     .emit();
@@ -942,7 +968,7 @@ fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId) {
                         self_ty.span,
                         |lint| {
                             let mut db = lint.build(msg);
-                            db.span_suggestion(self_ty.span, &replace, sugg, app);
+                            db.span_suggestion(self_ty.span, sugg_label, sugg, app);
                             db.emit()
                         },
                     );
@@ -1178,12 +1204,12 @@ pub fn instantiate_value_path(
         let mut user_self_ty = None;
         let mut is_alias_variant_ctor = false;
         match res {
-            Res::Def(DefKind::Ctor(CtorOf::Variant, _), _) => {
-                if let Some(self_ty) = self_ty {
-                    let adt_def = self_ty.ty_adt_def().unwrap();
-                    user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did, self_ty });
-                    is_alias_variant_ctor = true;
-                }
+            Res::Def(DefKind::Ctor(CtorOf::Variant, _), _)
+                if let Some(self_ty) = self_ty =>
+            {
+                let adt_def = self_ty.ty_adt_def().unwrap();
+                user_self_ty = Some(UserSelfTy { impl_def_id: adt_def.did, self_ty });
+                is_alias_variant_ctor = true;
             }
             Res::Def(DefKind::AssocFn | DefKind::AssocConst, def_id) => {
                 let container = tcx.associated_item(def_id).container;
index 9952413353fa9ca04328d40131abbc67c75756af..9efb52a08b7e10eb98daaab1dd43f2bebf7b5987 100644 (file)
@@ -29,6 +29,7 @@
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn check_casts(&self) {
         let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
+        debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
         for cast in deferred_cast_checks.drain(..) {
             cast.check(self);
         }
@@ -936,7 +937,7 @@ fn point_at_arg_instead_of_call_if_possible(
                         let ty = self.resolve_vars_if_possible(ty);
                         // We walk the argument type because the argument's type could have
                         // been `Option<T>`, but the `FulfillmentError` references `T`.
-                        if ty.walk().any(|arg| arg == predicate.self_ty().into()) {
+                        if ty.walk(self.tcx).any(|arg| arg == predicate.self_ty().into()) {
                             Some(i)
                         } else {
                             None
index 16f3de58078ac1c4c747221652990eb68d103dd7..9c70d2cb365b2714ff563cca9402aa7ff2c7b44d 100644 (file)
@@ -180,10 +180,6 @@ fn item_def_id(&self) -> Option<DefId> {
         None
     }
 
-    fn default_constness_for_trait_bounds(&self) -> hir::Constness {
-        self.tcx.hir().get(self.body_id).constness_for_typeck()
-    }
-
     fn get_type_parameter_bounds(
         &self,
         _: Span,
index b5bc9d3599acbf78435a0aac31394514e38acaa0..5c8056b244242343791656967f54d2cd9a92f61a 100644 (file)
@@ -5,9 +5,9 @@
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{Adt, Ref, Ty};
+use rustc_middle::ty::{Adt, Array, Ref, Ty};
 use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS;
-use rustc_span::symbol::kw::Underscore;
+use rustc_span::symbol::kw::{Empty, Underscore};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
@@ -38,10 +38,20 @@ pub(super) fn lint_dot_call_from_2018(
             return;
         }
 
-        // These are the method names that were added to prelude in Rust 2021
-        if !matches!(segment.ident.name, sym::try_into) {
-            return;
-        }
+        let prelude_or_array_lint = match segment.ident.name {
+            // `try_into` was added to the prelude in Rust 2021.
+            sym::try_into => RUST_2021_PRELUDE_COLLISIONS,
+            // `into_iter` wasn't added to the prelude,
+            // but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter
+            // before Rust 2021, which results in the same problem.
+            // It is only a problem for arrays.
+            sym::into_iter if let Array(..) = self_ty.kind() => {
+                // In this case, it wasn't really a prelude addition that was the problem.
+                // Instead, the problem is that the array-into_iter hack will no longer apply in Rust 2021.
+                rustc_lint::ARRAY_INTO_ITER
+            }
+            _ => return,
+        };
 
         // No need to lint if method came from std/core, as that will now be in the prelude
         if matches!(self.tcx.crate_name(pick.item.def_id.krate), sym::std | sym::core) {
@@ -69,7 +79,7 @@ pub(super) fn lint_dot_call_from_2018(
             // Inherent impls only require not relying on autoref and autoderef in order to
             // ensure that the trait implementation won't be used
             self.tcx.struct_span_lint_hir(
-                RUST_2021_PRELUDE_COLLISIONS,
+                prelude_or_array_lint,
                 self_expr.hir_id,
                 self_expr.span,
                 |lint| {
@@ -130,7 +140,7 @@ pub(super) fn lint_dot_call_from_2018(
             // trait implementations require full disambiguation to not clash with the new prelude
             // additions (i.e. convert from dot-call to fully-qualified call)
             self.tcx.struct_span_lint_hir(
-                RUST_2021_PRELUDE_COLLISIONS,
+                prelude_or_array_lint,
                 call_expr.hir_id,
                 call_expr.span,
                 |lint| {
@@ -146,15 +156,16 @@ pub(super) fn lint_dot_call_from_2018(
                         segment.ident.name
                     ));
 
-                    let (self_adjusted, precise) = self.adjust_expr(pick, self_expr);
+                    let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
                     if precise {
                         let args = args
                             .iter()
                             .skip(1)
                             .map(|arg| {
+                                let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
                                 format!(
                                     ", {}",
-                                    self.sess().source_map().span_to_snippet(arg.span).unwrap()
+                                    self.sess().source_map().span_to_snippet(span).unwrap()
                                 )
                             })
                             .collect::<String>();
@@ -163,8 +174,22 @@ pub(super) fn lint_dot_call_from_2018(
                             sp,
                             "disambiguate the associated function",
                             format!(
-                                "{}::{}({}{})",
-                                trait_name, segment.ident.name, self_adjusted, args
+                                "{}::{}{}({}{})",
+                                trait_name,
+                                segment.ident.name,
+                                if let Some(args) = segment.args.as_ref().and_then(|args| self
+                                    .sess()
+                                    .source_map()
+                                    .span_to_snippet(args.span_ext)
+                                    .ok())
+                                {
+                                    // Keep turbofish.
+                                    format!("::{}", args)
+                                } else {
+                                    String::new()
+                                },
+                                self_adjusted,
+                                args,
                             ),
                             Applicability::MachineApplicable,
                         );
@@ -239,47 +264,57 @@ pub(super) fn lint_fully_qualified_call_from_2018(
             let trait_path = self.trait_path_or_bare_name(span, expr_id, pick.item.container.id());
             let trait_generics = self.tcx.generics_of(pick.item.container.id());
 
-            let parameter_count = trait_generics.count() - (trait_generics.has_self as usize);
-            let trait_name = if parameter_count == 0 {
-                trait_path
-            } else {
-                format!(
-                    "{}<{}>",
-                    trait_path,
-                    std::iter::repeat("_").take(parameter_count).collect::<Vec<_>>().join(", ")
-                )
-            };
+            let trait_name =
+                if trait_generics.params.len() <= trait_generics.has_self as usize {
+                    trait_path
+                } else {
+                    let counts = trait_generics.own_counts();
+                    format!(
+                        "{}<{}>",
+                        trait_path,
+                        std::iter::repeat("'_")
+                            .take(counts.lifetimes)
+                            .chain(std::iter::repeat("_").take(
+                                counts.types + counts.consts - trait_generics.has_self as usize
+                            ))
+                            .collect::<Vec<_>>()
+                            .join(", ")
+                    )
+                };
 
             let mut lint = lint.build(&format!(
                 "trait-associated function `{}` will become ambiguous in Rust 2021",
                 method_name.name
             ));
 
-            let self_ty_name = self
-                .sess()
-                .source_map()
-                .span_to_snippet(self_ty_span)
-                .unwrap_or_else(|_| self_ty.to_string());
-
-            let self_ty_generics_count = match self_ty.kind() {
-                // Get the number of generics the self type has (if an Adt) unless we can determine that
-                // the user has written the self type with generics already which we (naively) do by looking
-                // for a "<" in `self_ty_name`.
-                Adt(def, _) if !self_ty_name.contains('<') => self.tcx.generics_of(def.did).count(),
-                _ => 0,
-            };
-            let self_ty_generics = if self_ty_generics_count > 0 {
-                format!("<{}>", vec!["_"; self_ty_generics_count].join(", "))
-            } else {
-                String::new()
-            };
+            let mut self_ty_name = self_ty_span
+                .find_ancestor_inside(span)
+                .and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
+                .unwrap_or_else(|| self_ty.to_string());
+
+            // Get the number of generics the self type has (if an Adt) unless we can determine that
+            // the user has written the self type with generics already which we (naively) do by looking
+            // for a "<" in `self_ty_name`.
+            if !self_ty_name.contains('<') {
+                if let Adt(def, _) = self_ty.kind() {
+                    let generics = self.tcx.generics_of(def.did);
+                    if !generics.params.is_empty() {
+                        let counts = generics.own_counts();
+                        self_ty_name += &format!(
+                            "<{}>",
+                            std::iter::repeat("'_")
+                                .take(counts.lifetimes)
+                                .chain(std::iter::repeat("_").take(counts.types + counts.consts))
+                                .collect::<Vec<_>>()
+                                .join(", ")
+                        );
+                    }
+                }
+            }
             lint.span_suggestion(
                 span,
                 "disambiguate the associated function",
-                format!(
-                    "<{}{} as {}>::{}",
-                    self_ty_name, self_ty_generics, trait_name, method_name.name,
-                ),
+                format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
                 Applicability::MachineApplicable,
             );
 
@@ -322,7 +357,12 @@ fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Opt
             .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None })
             .next();
         if let Some(any_id) = any_id {
-            return Some(format!("{}", any_id));
+            if any_id.name == Empty {
+                // Glob import, so just use its name.
+                return None;
+            } else {
+                return Some(format!("{}", any_id));
+            }
         }
 
         // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick,
@@ -344,7 +384,12 @@ fn trait_path(&self, span: Span, expr_hir_id: HirId, trait_def_id: DefId) -> Opt
     /// Creates a string version of the `expr` that includes explicit adjustments.
     /// Returns the string and also a bool indicating whther this is a *precise*
     /// suggestion.
-    fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) {
+    fn adjust_expr(
+        &self,
+        pick: &Pick<'tcx>,
+        expr: &hir::Expr<'tcx>,
+        outer: Span,
+    ) -> (String, bool) {
         let derefs = "*".repeat(pick.autoderefs);
 
         let autoref = match pick.autoref_or_ptr_adjustment {
@@ -353,12 +398,15 @@ fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, boo
             Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
         };
 
-        let (expr_text, precise) =
-            if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
-                (expr_text, true)
-            } else {
-                ("(..)".to_string(), false)
-            };
+        let (expr_text, precise) = if let Some(expr_text) = expr
+            .span
+            .find_ancestor_inside(outer)
+            .and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
+        {
+            (expr_text, true)
+        } else {
+            ("(..)".to_string(), false)
+        };
 
         let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
             pick.autoref_or_ptr_adjustment
index 486e4d15d6580de4f251e985fe46496b16072965..1c7d68a3d57d4325120a0586c07af81d385d9a64 100644 (file)
@@ -616,32 +616,30 @@ fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'t
         let lang_items = self.tcx.lang_items();
 
         match *self_ty.value.value.kind() {
-            ty::Dynamic(ref data, ..) => {
-                if let Some(p) = data.principal() {
-                    // Subtle: we can't use `instantiate_query_response` here: using it will
-                    // commit to all of the type equalities assumed by inference going through
-                    // autoderef (see the `method-probe-no-guessing` test).
-                    //
-                    // However, in this code, it is OK if we end up with an object type that is
-                    // "more general" than the object type that we are evaluating. For *every*
-                    // object type `MY_OBJECT`, a function call that goes through a trait-ref
-                    // of the form `<MY_OBJECT as SuperTraitOf(MY_OBJECT)>::func` is a valid
-                    // `ObjectCandidate`, and it should be discoverable "exactly" through one
-                    // of the iterations in the autoderef loop, so there is no problem with it
-                    // being discoverable in another one of these iterations.
-                    //
-                    // Using `instantiate_canonical_with_fresh_inference_vars` on our
-                    // `Canonical<QueryResponse<Ty<'tcx>>>` and then *throwing away* the
-                    // `CanonicalVarValues` will exactly give us such a generalization - it
-                    // will still match the original object type, but it won't pollute our
-                    // type variables in any form, so just do that!
-                    let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) =
-                        self.fcx
-                            .instantiate_canonical_with_fresh_inference_vars(self.span, &self_ty);
-
-                    self.assemble_inherent_candidates_from_object(generalized_self_ty);
-                    self.assemble_inherent_impl_candidates_for_type(p.def_id());
-                }
+            ty::Dynamic(ref data, ..) if let Some(p) = data.principal() => {
+                // Subtle: we can't use `instantiate_query_response` here: using it will
+                // commit to all of the type equalities assumed by inference going through
+                // autoderef (see the `method-probe-no-guessing` test).
+                //
+                // However, in this code, it is OK if we end up with an object type that is
+                // "more general" than the object type that we are evaluating. For *every*
+                // object type `MY_OBJECT`, a function call that goes through a trait-ref
+                // of the form `<MY_OBJECT as SuperTraitOf(MY_OBJECT)>::func` is a valid
+                // `ObjectCandidate`, and it should be discoverable "exactly" through one
+                // of the iterations in the autoderef loop, so there is no problem with it
+                // being discoverable in another one of these iterations.
+                //
+                // Using `instantiate_canonical_with_fresh_inference_vars` on our
+                // `Canonical<QueryResponse<Ty<'tcx>>>` and then *throwing away* the
+                // `CanonicalVarValues` will exactly give us such a generalization - it
+                // will still match the original object type, but it won't pollute our
+                // type variables in any form, so just do that!
+                let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) =
+                    self.fcx
+                        .instantiate_canonical_with_fresh_inference_vars(self.span, &self_ty);
+
+                self.assemble_inherent_candidates_from_object(generalized_self_ty);
+                self.assemble_inherent_impl_candidates_for_type(p.def_id());
             }
             ty::Adt(def, _) => {
                 self.assemble_inherent_impl_candidates_for_type(def.did);
index 1d5a9e3e1f968fed8efab7a6820e5467af12da6f..c60d82d0cabc579e819b76f6cbac2049b53f818e 100644 (file)
@@ -6,8 +6,7 @@
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
-use rustc_hir::intravisit;
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -70,15 +69,13 @@ fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
 
     pub fn report_method_error(
         &self,
-        span: Span,
+        mut span: Span,
         rcvr_ty: Ty<'tcx>,
         item_name: Ident,
         source: SelfSource<'tcx>,
         error: MethodError<'tcx>,
         args: Option<&'tcx [hir::Expr<'tcx>]>,
     ) -> Option<DiagnosticBuilder<'_>> {
-        let orig_span = span;
-        let mut span = span;
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
             return None;
@@ -545,7 +542,6 @@ pub fn report_method_error(
                     } else {
                         err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
                     }
-                    self.tcx.sess.trait_methods_not_found.borrow_mut().insert(orig_span);
                 };
 
                 // If the method name is the name of a field with a function or closure type,
@@ -1014,9 +1010,7 @@ fn suggest_use_candidates(
         candidates: Vec<DefId>,
     ) {
         let module_did = self.tcx.parent_module(self.body_id);
-        let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
-        let krate = self.tcx.hir().krate();
-        let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
+        let (span, found_use) = find_use_placement(self.tcx, module_did);
         if let Some(span) = span {
             let path_strings = candidates.iter().map(|did| {
                 // Produce an additional newline to separate the new use statement
@@ -1609,64 +1603,38 @@ pub fn provide(providers: &mut ty::query::Providers) {
     providers.all_traits = compute_all_traits;
 }
 
-struct UsePlacementFinder<'tcx> {
-    target_module: hir::HirId,
-    span: Option<Span>,
-    found_use: bool,
-    tcx: TyCtxt<'tcx>,
-}
-
-impl UsePlacementFinder<'tcx> {
-    fn check(
-        tcx: TyCtxt<'tcx>,
-        krate: &'tcx hir::Crate<'tcx>,
-        target_module: hir::HirId,
-    ) -> (Option<Span>, bool) {
-        let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
-        intravisit::walk_crate(&mut finder, krate);
-        (finder.span, finder.found_use)
-    }
-}
-
-impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
-    fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
-        if self.span.is_some() {
-            return;
-        }
-        if hir_id != self.target_module {
-            intravisit::walk_mod(self, module, hir_id);
-            return;
-        }
-        // Find a `use` statement.
-        for &item_id in module.item_ids {
-            let item = self.tcx.hir().item(item_id);
-            match item.kind {
-                hir::ItemKind::Use(..) => {
-                    // Don't suggest placing a `use` before the prelude
-                    // import or other generated ones.
-                    if !item.span.from_expansion() {
-                        self.span = Some(item.span.shrink_to_lo());
-                        self.found_use = true;
-                        return;
-                    }
+fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option<Span>, bool) {
+    let mut span = None;
+    let mut found_use = false;
+    let (module, _, _) = tcx.hir().get_module(target_module);
+
+    // Find a `use` statement.
+    for &item_id in module.item_ids {
+        let item = tcx.hir().item(item_id);
+        match item.kind {
+            hir::ItemKind::Use(..) => {
+                // Don't suggest placing a `use` before the prelude
+                // import or other generated ones.
+                if !item.span.from_expansion() {
+                    span = Some(item.span.shrink_to_lo());
+                    found_use = true;
+                    break;
                 }
-                // Don't place `use` before `extern crate`...
-                hir::ItemKind::ExternCrate(_) => {}
-                // ...but do place them before the first other item.
-                _ => {
-                    if self.span.map_or(true, |span| item.span < span) {
-                        if !item.span.from_expansion() {
-                            self.span = Some(item.span.shrink_to_lo());
-                            // Don't insert between attributes and an item.
-                            let attrs = self.tcx.hir().attrs(item.hir_id());
-                            // Find the first attribute on the item.
-                            // FIXME: This is broken for active attributes.
-                            for attr in attrs {
-                                if !attr.span.is_dummy()
-                                    && self.span.map_or(true, |span| attr.span < span)
-                                {
-                                    self.span = Some(attr.span.shrink_to_lo());
-                                }
+            }
+            // Don't place `use` before `extern crate`...
+            hir::ItemKind::ExternCrate(_) => {}
+            // ...but do place them before the first other item.
+            _ => {
+                if span.map_or(true, |span| item.span < span) {
+                    if !item.span.from_expansion() {
+                        span = Some(item.span.shrink_to_lo());
+                        // Don't insert between attributes and an item.
+                        let attrs = tcx.hir().attrs(item.hir_id());
+                        // Find the first attribute on the item.
+                        // FIXME: This is broken for active attributes.
+                        for attr in attrs {
+                            if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) {
+                                span = Some(attr.span.shrink_to_lo());
                             }
                         }
                     }
@@ -1675,11 +1643,7 @@ fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirI
         }
     }
 
-    type Map = intravisit::ErasedMap<'tcx>;
-
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
+    (span, found_use)
 }
 
 fn print_disambiguation_help(
index 2a196644dac9dd3be052cbca4bc0d0f59e471073..803c440bbc98b3ae6f06aed391238390d38ea9df 100644 (file)
@@ -364,7 +364,7 @@ fn typeck_with_fallback<'tcx>(
 
     let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
         let param_env = tcx.param_env(def_id);
-        let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
+        let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
             let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
                 let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
                 <dyn AstConv<'_>>::ty_of_fn(
@@ -383,17 +383,25 @@ fn typeck_with_fallback<'tcx>(
 
             check_abi(tcx, id, span, fn_sig.abi());
 
+            // When normalizing the function signature, we assume all types are
+            // well-formed. So, we don't need to worry about the obligations
+            // from normalization. We could just discard these, but to align with
+            // compare_method and elsewhere, we just add implied bounds for
+            // these types.
+            let mut wf_tys = vec![];
             // Compute the fty from point of view of inside the fn.
             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
+            wf_tys.extend(fn_sig.inputs_and_output.iter());
             let fn_sig = inh.normalize_associated_types_in(
                 body.value.span,
                 body_id.hir_id,
                 param_env,
                 fn_sig,
             );
+            wf_tys.extend(fn_sig.inputs_and_output.iter());
 
             let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0;
-            fcx
+            (fcx, wf_tys)
         } else {
             let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
             let expected_type = body_ty
@@ -443,14 +451,15 @@ fn typeck_with_fallback<'tcx>(
 
             fcx.write_ty(id, expected_type);
 
-            fcx
+            (fcx, vec![])
         };
 
-        fcx.type_inference_fallback();
+        let fallback_has_occurred = fcx.type_inference_fallback();
 
         // Even though coercion casts provide type hints, we check casts after fallback for
         // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
         fcx.check_casts();
+        fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
 
         // Closure and generator analysis may run after fallback
         // because they don't constrain other type variables.
@@ -466,7 +475,7 @@ fn typeck_with_fallback<'tcx>(
         fcx.select_all_obligations_or_error();
 
         if fn_sig.is_some() {
-            fcx.regionck_fn(id, body);
+            fcx.regionck_fn(id, body, span, &wf_tys);
         } else {
             fcx.regionck_expr(body);
         }
index 963436d05d8ef30a52bac21eb8c15855f9635c4f..9b495fba1975d01824abb7bb3095de2458d9c289 100644 (file)
@@ -428,7 +428,7 @@ fn check_overloaded_binop(
                     }
                 }
                 if let Some(missing_trait) = missing_trait {
-                    let mut visitor = TypeParamVisitor(vec![]);
+                    let mut visitor = TypeParamVisitor(self.tcx, vec![]);
                     visitor.visit_ty(lhs_ty);
 
                     if op.node == hir::BinOpKind::Add
@@ -439,7 +439,7 @@ fn check_overloaded_binop(
                         // This has nothing here because it means we did string
                         // concatenation (e.g., "Hello " + "World!"). This means
                         // we don't want the note in the else clause to be emitted
-                    } else if let [ty] = &visitor.0[..] {
+                    } else if let [ty] = &visitor.1[..] {
                         if let ty::Param(p) = *ty.kind() {
                             // Check if the method would be found if the type param wasn't
                             // involved. If so, it means that adding a trait bound to the param is
@@ -1003,12 +1003,15 @@ fn suggest_constraining_param(
     }
 }
 
-struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
+struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
 
 impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.0)
+    }
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         if let ty::Param(_) = ty.kind() {
-            self.0.push(ty);
+            self.1.push(ty);
         }
         ty.super_visit_with(self)
     }
index dae574bb7bf0fa04123ddf7b9647e7af7bbdc050..140a9d1126d32a29289207c7f7df4bc3884943c8 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Ident;
-use rustc_span::{BytePos, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, DUMMY_SP};
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::{ObligationCause, Pattern};
 use ty::VariantDef;
@@ -627,15 +627,15 @@ fn borrow_pat_suggestion(
             let binding_parent = tcx.hir().get(binding_parent_id);
             debug!("inner {:?} pat {:?} parent {:?}", inner, pat, binding_parent);
             match binding_parent {
-                hir::Node::Param(hir::Param { span, .. }) => {
-                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
-                        err.span_suggestion(
-                            *span,
-                            &format!("did you mean `{}`", snippet),
-                            format!(" &{}", expected),
-                            Applicability::MachineApplicable,
-                        );
-                    }
+                hir::Node::Param(hir::Param { span, .. })
+                    if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) =>
+                {
+                    err.span_suggestion(
+                        *span,
+                        &format!("did you mean `{}`", snippet),
+                        format!(" &{}", expected),
+                        Applicability::MachineApplicable,
+                    );
                 }
                 hir::Node::Arm(_) | hir::Node::Pat(_) => {
                     // rely on match ergonomics or it might be nested `&&pat`
@@ -990,10 +990,25 @@ fn e0023(
     ) {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
+
+        let subpat_spans = if subpats.is_empty() {
+            vec![pat_span]
+        } else {
+            subpats.iter().map(|p| p.span).collect()
+        };
+        let last_subpat_span = *subpat_spans.last().unwrap();
         let res_span = self.tcx.def_span(res.def_id());
+        let def_ident_span = self.tcx.def_ident_span(res.def_id()).unwrap_or(res_span);
+        let field_def_spans = if fields.is_empty() {
+            vec![res_span]
+        } else {
+            fields.iter().map(|f| f.ident.span).collect()
+        };
+        let last_field_def_span = *field_def_spans.last().unwrap();
+
         let mut err = struct_span_err!(
             self.tcx.sess,
-            pat_span,
+            MultiSpan::from_spans(subpat_spans),
             E0023,
             "this pattern has {} field{}, but the corresponding {} has {} field{}",
             subpats.len(),
@@ -1003,10 +1018,22 @@ fn e0023(
             fields_ending,
         );
         err.span_label(
-            pat_span,
-            format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len(),),
-        )
-        .span_label(res_span, format!("{} defined here", res.descr()));
+            last_subpat_span,
+            &format!("expected {} field{}, found {}", fields.len(), fields_ending, subpats.len()),
+        );
+        if self.tcx.sess.source_map().is_multiline(qpath.span().between(last_subpat_span)) {
+            err.span_label(qpath.span(), "");
+        }
+        if self.tcx.sess.source_map().is_multiline(def_ident_span.between(last_field_def_span)) {
+            err.span_label(def_ident_span, format!("{} defined here", res.descr()));
+        }
+        for span in &field_def_spans[..field_def_spans.len() - 1] {
+            err.span_label(*span, "");
+        }
+        err.span_label(
+            last_field_def_span,
+            &format!("{} has {} field{}", res.descr(), fields.len(), fields_ending),
+        );
 
         // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
         // More generally, the expected type wants a tuple variant with one field of an
@@ -1293,13 +1320,12 @@ fn check_struct_pat_fields(
             (Some(mut err), None) => {
                 err.emit();
             }
-            (None, None) => {
-                if let Some(mut err) =
-                    self.error_tuple_variant_index_shorthand(variant, pat, fields)
-                {
-                    err.emit();
-                }
+            (None, None) if let Some(mut err) =
+                    self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
+            {
+                err.emit();
             }
+            (None, None) => {}
         }
         no_field_errors
     }
index ca6828cfdf68de599fee44ff104038bbb081a59c..290fa5fc36719278954ab0e9963399234d2d9ff3 100644 (file)
@@ -144,11 +144,20 @@ pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]
     /// rest of type check and because sometimes we need type
     /// inference to have completed before we can determine which
     /// constraints to add.
-    pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>) {
+    pub(crate) fn regionck_fn(
+        &self,
+        fn_id: hir::HirId,
+        body: &'tcx hir::Body<'tcx>,
+        span: Span,
+        wf_tys: &[Ty<'tcx>],
+    ) {
         debug!("regionck_fn(id={})", fn_id);
         let subject = self.tcx.hir().body_owner_def_id(body.id());
         let hir_id = body.value.hir_id;
         let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env);
+        // We need to add the implied bounds from the function signature
+        rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id, span);
+        rcx.outlives_environment.save_implied_bounds(fn_id);
 
         if !self.errors_reported_since_creation() {
             // regionck assumes typeck succeeded
index fc7f55e24b2f3dbc603e96f67a19e3f184ecc7e8..702f69a9fcf0ba2381c181d97a40fefb78d93f53 100644 (file)
@@ -47,7 +47,7 @@
 };
 use rustc_session::lint;
 use rustc_span::sym;
-use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 use rustc_data_structures::stable_map::FxHashMap;
@@ -400,6 +400,11 @@ fn process_collected_capture_information(
             };
 
             capture_info.capture_kind = capture_kind;
+            let capture_info = if let Some(existing) = processed.get(&place) {
+                determine_capture_info(*existing, capture_info)
+            } else {
+                capture_info
+            };
             processed.insert(place, capture_info);
         }
 
@@ -489,7 +494,7 @@ fn compute_min_captures(
         let mut root_var_min_capture_list =
             typeck_results.closure_min_captures.remove(&closure_def_id).unwrap_or_default();
 
-        for (place, capture_info) in capture_information.into_iter() {
+        for (mut place, capture_info) in capture_information.into_iter() {
             let var_hir_id = match place.base {
                 PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
                 base => bug!("Expected upvar, found={:?}", base),
@@ -530,14 +535,12 @@ fn compute_min_captures(
 
                         // Truncate the descendant (already in min_captures) to be same as the ancestor to handle any
                         // possible change in capture mode.
-                        let (_, descendant_capture_kind) = truncate_place_to_len(
-                            possible_descendant.place,
-                            possible_descendant.info.capture_kind,
+                        truncate_place_to_len_and_update_capture_kind(
+                            &mut possible_descendant.place,
+                            &mut possible_descendant.info.capture_kind,
                             place.projections.len(),
                         );
 
-                        possible_descendant.info.capture_kind = descendant_capture_kind;
-
                         updated_capture_info =
                             determine_capture_info(updated_capture_info, possible_descendant.info);
 
@@ -561,14 +564,12 @@ fn compute_min_captures(
 
                             // Truncate the descendant (current place) to be same as the ancestor to handle any
                             // possible change in capture mode.
-                            let (_, descendant_capture_kind) = truncate_place_to_len(
-                                place.clone(),
-                                updated_capture_info.capture_kind,
+                            truncate_place_to_len_and_update_capture_kind(
+                                &mut place,
+                                &mut updated_capture_info.capture_kind,
                                 possible_ancestor.place.projections.len(),
                             );
 
-                            updated_capture_info.capture_kind = descendant_capture_kind;
-
                             possible_ancestor.info = determine_capture_info(
                                 possible_ancestor.info,
                                 updated_capture_info,
@@ -679,17 +680,32 @@ fn perform_2229_migration_anaysis(
                         migrated_variables_concat
                     );
 
-                    let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
+                    let mut closure_body_span = {
+                        // If the body was entirely expanded from a macro
+                        // invocation, i.e. the body is not contained inside the
+                        // closure span, then we walk up the expansion until we
+                        // find the span before the expansion.
+                        let s = self.tcx.hir().span(body_id.hir_id);
+                        s.find_ancestor_inside(closure_span).unwrap_or(s)
+                    };
 
-                    // If the body was entirely expanded from a macro
-                    // invocation, i.e. the body is not contained inside the
-                    // closure span, then we walk up the expansion until we
-                    // find the span before the expansion.
-                    while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
-                        closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
-                    }
+                    if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
+                        if s.starts_with('$') {
+                            // Looks like a macro fragment. Try to find the real block.
+                            if let Some(hir::Node::Expr(&hir::Expr {
+                                kind: hir::ExprKind::Block(block, ..), ..
+                            })) = self.tcx.hir().find(body_id.hir_id) {
+                                // If the body is a block (with `{..}`), we use the span of that block.
+                                // E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`.
+                                // Since we know it's a block, we know we can insert the `let _ = ..` without
+                                // breaking the macro syntax.
+                                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(block.span) {
+                                    closure_body_span = block.span;
+                                    s = snippet;
+                                }
+                            }
+                        }
 
-                    if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
                         let mut lines = s.lines();
                         let line1 = lines.next().unwrap_or_default();
 
@@ -1476,7 +1492,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     place: &Place<'tcx>,
-    curr_borrow_kind: ty::UpvarCapture<'tcx>,
+    mut curr_borrow_kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let pos = place.projections.iter().enumerate().position(|(i, p)| {
         let ty = place.ty_before_projection(i);
@@ -1485,7 +1501,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
         match p.kind {
             ProjectionKind::Field(..) => match ty.kind() {
                 ty::Adt(def, _) if def.repr.packed() => {
-                    match tcx.layout_raw(param_env.and(p.ty)) {
+                    match tcx.layout_of(param_env.and(p.ty)) {
                         Ok(layout) if layout.align.abi.bytes() == 1 => {
                             // if the alignment is 1, the type can't be further
                             // disaligned.
@@ -1508,13 +1524,13 @@ fn restrict_repr_packed_field_ref_capture<'tcx>(
         }
     });
 
-    let place = place.clone();
+    let mut place = place.clone();
 
     if let Some(pos) = pos {
-        truncate_place_to_len(place, curr_borrow_kind, pos)
-    } else {
-        (place, curr_borrow_kind)
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_borrow_kind, pos);
     }
+
+    (place, curr_borrow_kind)
 }
 
 /// Returns a Ty that applies the specified capture kind on the provided capture Ty
@@ -1841,31 +1857,28 @@ fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: hir::H
 ///   them completely.
 /// - No projections are applied on top of Union ADTs, since these require unsafe blocks.
 fn restrict_precision_for_unsafe(
-    place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    if place.projections.is_empty() {
-        // Nothing to do here
-        return (place, curr_mode);
-    }
-
     if place.base_ty.is_unsafe_ptr() {
-        return truncate_place_to_len(place, curr_mode, 0);
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
     }
 
     if place.base_ty.is_union() {
-        return truncate_place_to_len(place, curr_mode, 0);
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, 0);
     }
 
     for (i, proj) in place.projections.iter().enumerate() {
         if proj.ty.is_unsafe_ptr() {
             // Don't apply any projections on top of an unsafe ptr.
-            return truncate_place_to_len(place, curr_mode, i + 1);
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
+            break;
         }
 
         if proj.ty.is_union() {
             // Don't capture preicse fields of a union.
-            return truncate_place_to_len(place, curr_mode, i + 1);
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i + 1);
+            break;
         }
     }
 
@@ -1880,7 +1893,7 @@ fn restrict_capture_precision<'tcx>(
     place: Place<'tcx>,
     curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    let (place, curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
+    let (mut place, mut curr_mode) = restrict_precision_for_unsafe(place, curr_mode);
 
     if place.projections.is_empty() {
         // Nothing to do here
@@ -1891,7 +1904,8 @@ fn restrict_capture_precision<'tcx>(
         match proj.kind {
             ProjectionKind::Index => {
                 // Arrays are completely captured, so we drop Index projections
-                return truncate_place_to_len(place, curr_mode, i);
+                truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, i);
+                return (place, curr_mode);
             }
             ProjectionKind::Deref => {}
             ProjectionKind::Field(..) => {} // ignore
@@ -1902,67 +1916,42 @@ fn restrict_capture_precision<'tcx>(
     return (place, curr_mode);
 }
 
-/// Take ownership if data being accessed is owned by the variable used to access it
-/// (or if closure attempts to move data that it doesn’t own).
-/// Note: When taking ownership, only capture data found on the stack.
+/// Truncate deref of any reference.
 fn adjust_for_move_closure<'tcx>(
-    place: Place<'tcx>,
-    kind: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
-    let contains_deref_of_ref = place.deref_tys().any(|ty| ty.is_ref());
     let first_deref = place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
-    match kind {
-        ty::UpvarCapture::ByRef(..) if contains_deref_of_ref => (place, kind),
-
-        // If there's any Deref and the data needs to be moved into the closure body,
-        // or it's a Deref of a Box, truncate the path to the first deref
-        _ if first_deref.is_some() => {
-            let place = match first_deref {
-                Some(idx) => {
-                    let (place, _) = truncate_place_to_len(place, kind, idx);
-                    place
-                }
-                None => place,
-            };
-
-            // AMAN: I think we don't need the span inside the ByValue anymore
-            //       we have more detailed span in CaptureInfo
-            (place, ty::UpvarCapture::ByValue(None))
-        }
-
-        _ => (place, ty::UpvarCapture::ByValue(None)),
+    if let Some(idx) = first_deref {
+        truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
     }
+
+    // AMAN: I think we don't need the span inside the ByValue anymore
+    //       we have more detailed span in CaptureInfo
+    (place, ty::UpvarCapture::ByValue(None))
 }
 
 /// Adjust closure capture just that if taking ownership of data, only move data
 /// from enclosing stack frame.
 fn adjust_for_non_move_closure<'tcx>(
-    place: Place<'tcx>,
+    mut place: Place<'tcx>,
     mut kind: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let contains_deref =
         place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);
 
     match kind {
-        ty::UpvarCapture::ByValue(..) if contains_deref.is_some() => {
-            let place = match contains_deref {
-                Some(idx) => {
-                    let (place, new_kind) = truncate_place_to_len(place, kind, idx);
-
-                    kind = new_kind;
-                    place
-                }
-                // Because of the if guard on the match on `kind`, we should never get here.
-                None => unreachable!(),
-            };
-
-            (place, kind)
+        ty::UpvarCapture::ByValue(..) => {
+            if let Some(idx) = contains_deref {
+                truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
+            }
         }
 
-        ty::UpvarCapture::ByValue(..) => (place, kind),
-        ty::UpvarCapture::ByRef(..) => (place, kind),
+        ty::UpvarCapture::ByRef(..) => {}
     }
+
+    (place, kind)
 }
 
 fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
@@ -2157,15 +2146,13 @@ fn determine_capture_info(
 ///
 /// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place`
 /// contained `Deref` of `&mut`.
-fn truncate_place_to_len(
-    mut place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+fn truncate_place_to_len_and_update_capture_kind(
+    place: &mut Place<'tcx>,
+    curr_mode: &mut ty::UpvarCapture<'tcx>,
     len: usize,
-) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
+) {
     let is_mut_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Mut));
 
-    let mut capture_kind = curr_mode;
-
     // If the truncated part of the place contains `Deref` of a `&mut` then convert MutBorrow ->
     // UniqueImmBorrow
     // Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
@@ -2176,7 +2163,7 @@ fn truncate_place_to_len(
                 if place.projections[i].kind == ProjectionKind::Deref
                     && is_mut_ref(place.ty_before_projection(i))
                 {
-                    capture_kind = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
+                    *curr_mode = ty::UpvarCapture::ByRef(ty::UpvarBorrow {
                         kind: ty::BorrowKind::UniqueImmBorrow,
                         region,
                     });
@@ -2190,8 +2177,6 @@ fn truncate_place_to_len(
     }
 
     place.projections.truncate(len);
-
-    (place, capture_kind)
 }
 
 /// Determines the Ancestry relationship of Place A relative to Place B
@@ -2256,8 +2241,8 @@ fn determine_place_ancestry_relation(
 /// }
 /// ```
 fn truncate_capture_for_optimization<'tcx>(
-    place: Place<'tcx>,
-    curr_mode: ty::UpvarCapture<'tcx>,
+    mut place: Place<'tcx>,
+    mut curr_mode: ty::UpvarCapture<'tcx>,
 ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) {
     let is_shared_ref = |ty: Ty<'_>| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not));
 
@@ -2269,10 +2254,12 @@ fn truncate_capture_for_optimization<'tcx>(
     match idx {
         // If that pointer is a shared reference, then we don't need those fields.
         Some(idx) if is_shared_ref(place.ty_before_projection(idx)) => {
-            truncate_place_to_len(place, curr_mode, idx + 1)
+            truncate_place_to_len_and_update_capture_kind(&mut place, &mut curr_mode, idx + 1)
         }
-        None | Some(_) => (place, curr_mode),
+        None | Some(_) => {}
     }
+
+    (place, curr_mode)
 }
 
 /// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
index b82437096592807b823b2f966ca3cf1bf80cb7da..17716afe3208fee68882fa83bdeb4d45cd6e6730 100644 (file)
@@ -290,7 +290,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
 
             let err_ty_str;
             let mut is_ptr = true;
-            let err = if tcx.features().const_generics {
+            let err = if tcx.features().adt_const_params {
                 match ty.peel_refs().kind() {
                     ty::FnPtr(_) => Some("function pointers"),
                     ty::RawPtr(_) => Some("raw pointers"),
@@ -328,7 +328,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                     err.note("the only supported types are integers, `bool` and `char`");
                     if tcx.sess.is_nightly_build() {
                         err.help(
-                            "more complex types are supported with `#![feature(const_generics)]`",
+                            "more complex types are supported with `#![feature(adt_const_params)]`",
                         );
                     }
                     err.emit()
@@ -541,10 +541,10 @@ fn check_type_defn<'tcx, F>(
                 fcx.register_predicate(traits::Obligation::new(
                     cause,
                     fcx.param_env,
-                    ty::PredicateKind::ConstEvaluatable(
+                    ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
                         ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
                         discr_substs,
-                    )
+                    ))
                     .to_predicate(tcx),
                 ));
             }
@@ -746,7 +746,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     // Ignore dependent defaults -- that is, where the default of one type
                     // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
                     // be sure if it will error or not as user might always specify the other.
-                    if !ty.needs_subst() {
+                    if !ty.definitely_needs_subst(tcx) {
                         fcx.register_wf_obligation(
                             ty.into(),
                             tcx.def_span(param.def_id),
@@ -762,7 +762,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                     // for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
                     // we should eagerly error.
                     let default_ct = tcx.const_param_default(param.def_id);
-                    if !default_ct.needs_subst() {
+                    if !default_ct.definitely_needs_subst(tcx) {
                         fcx.register_wf_obligation(
                             default_ct.into(),
                             tcx.def_span(param.def_id),
@@ -796,7 +796,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                 if is_our_default(param) {
                     let default_ty = tcx.type_of(param.def_id);
                     // ... and it's not a dependent default, ...
-                    if !default_ty.needs_subst() {
+                    if !default_ty.definitely_needs_subst(tcx) {
                         // ... then substitute it with the default.
                         return default_ty.into();
                     }
@@ -809,7 +809,7 @@ fn check_where_clauses<'tcx, 'fcx>(
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
                     // ... and it's not a dependent default, ...
-                    if !default_ct.needs_subst() {
+                    if !default_ct.definitely_needs_subst(tcx) {
                         // ... then substitute it with the default.
                         return default_ct.into();
                     }
@@ -825,12 +825,15 @@ fn check_where_clauses<'tcx, 'fcx>(
         .predicates
         .iter()
         .flat_map(|&(pred, sp)| {
-            #[derive(Default)]
-            struct CountParams {
+            struct CountParams<'tcx> {
+                tcx: TyCtxt<'tcx>,
                 params: FxHashSet<u32>,
             }
-            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
+            impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
                 type BreakTy = ();
+                fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+                    Some(self.tcx)
+                }
 
                 fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                     if let ty::Param(param) = t.kind() {
@@ -850,12 +853,12 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
                     c.super_visit_with(self)
                 }
             }
-            let mut param_count = CountParams::default();
+            let mut param_count = CountParams { tcx: fcx.tcx, params: FxHashSet::default() };
             let has_region = pred.visit_with(&mut param_count).is_break();
             let substituted_pred = pred.subst(tcx, substs);
             // Don't check non-defaulted params, dependent defaults (including lifetimes)
             // or preds with multiple params.
-            if substituted_pred.has_param_types_or_consts()
+            if substituted_pred.definitely_has_param_types_or_consts(tcx)
                 || param_count.params.len() > 1
                 || has_region
             {
@@ -908,6 +911,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
     }
 }
 
+#[tracing::instrument(level = "debug", skip(fcx, span, hir_decl))]
 fn check_fn_or_method<'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     span: Span,
@@ -918,6 +922,11 @@ fn check_fn_or_method<'fcx, 'tcx>(
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
 
+    // Unnormalized types in signature are WF too
+    implied_bounds.extend(sig.inputs());
+    // FIXME(#27579) return types should not be implied bounds
+    implied_bounds.push(sig.output());
+
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
     // on the entire `FnSig`, since this would use the same `WellFormedLoc`
@@ -967,9 +976,11 @@ fn check_fn_or_method<'fcx, 'tcx>(
         ObligationCauseCode::ReturnType,
     );
 
-    // FIXME(#25759) return types should not be implied bounds
+    // FIXME(#27579) return types should not be implied bounds
     implied_bounds.push(sig.output());
 
+    debug!(?implied_bounds);
+
     check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
 }
 
@@ -1049,26 +1060,24 @@ fn check_opaque_types<'fcx, 'tcx>(
                     let arg_is_param = match arg.unpack() {
                         GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
 
-                        GenericArgKind::Lifetime(region) => {
-                            if let ty::ReStatic = region {
-                                tcx.sess
-                                    .struct_span_err(
-                                        span,
-                                        "non-defining opaque type use in defining scope",
-                                    )
-                                    .span_label(
-                                        tcx.def_span(generics.param_at(i, tcx).def_id),
-                                        "cannot use static lifetime; use a bound lifetime \
-                                                 instead or remove the lifetime parameter from the \
-                                                 opaque type",
-                                    )
-                                    .emit();
-                                continue;
-                            }
-
-                            true
+                        GenericArgKind::Lifetime(region) if let ty::ReStatic = region => {
+                            tcx.sess
+                                .struct_span_err(
+                                    span,
+                                    "non-defining opaque type use in defining scope",
+                                )
+                                .span_label(
+                                    tcx.def_span(generics.param_at(i, tcx).def_id),
+                                    "cannot use static lifetime; use a bound lifetime \
+                                                instead or remove the lifetime parameter from the \
+                                                opaque type",
+                                )
+                                .emit();
+                            continue;
                         }
 
+                        GenericArgKind::Lifetime(_) => true,
+
                         GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
                     };
 
@@ -1116,6 +1125,7 @@ fn check_opaque_types<'fcx, 'tcx>(
      `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
      of the previous types except `Self`)";
 
+#[tracing::instrument(level = "debug", skip(fcx))]
 fn check_method_receiver<'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'tcx>,
     fn_sig: &hir::FnSig<'_>,
@@ -1379,7 +1389,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
     for obligation in implied_obligations {
         let pred = obligation.predicate;
         // Match the existing behavior.
-        if pred.is_global() && !pred.has_late_bound_regions() {
+        if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
             let pred = fcx.normalize_associated_types_in(span, pred);
             let obligation = traits::Obligation::new(
                 traits::ObligationCause::new(span, id, traits::TrivialBound),
index a13157b460828a809cf7a251dbde2164bf729a8a..c57ec9ef78f6856804cbe95c990e5b3b6a56241e 100644 (file)
@@ -130,7 +130,7 @@ fn tcx(&self) -> TyCtxt<'tcx> {
 
     fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
         debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
+        assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions(self.tcx()));
         self.typeck_results.node_types_mut().insert(hir_id, ty);
     }
 
@@ -175,10 +175,10 @@ fn fix_scalar_builtin_expr(&mut self, e: &hir::Expr<'_>) {
                                 }
                             }
                         }
-                        hir::ExprKind::AssignOp(..) => {
-                            if let Some(a) = typeck_results.adjustments_mut().get_mut(lhs.hir_id) {
-                                a.pop();
-                            }
+                        hir::ExprKind::AssignOp(..)
+                            if let Some(a) = typeck_results.adjustments_mut().get_mut(lhs.hir_id) =>
+                        {
+                            a.pop();
                         }
                         _ => {}
                     }
index 95d3bb1172305b391992e1b32b9364938e2a4ed2..cb127880c62b315c41ee3bb6547ef463cd1358a4 100644 (file)
@@ -9,8 +9,7 @@
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports = FxHashSet::default();
-    for &body_id in tcx.hir().krate().bodies.keys() {
-        let item_def_id = tcx.hir().body_owner_def_id(body_id);
+    for item_def_id in tcx.body_owners() {
         let imports = tcx.used_trait_imports(item_def_id);
         debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
         used_trait_imports.extend(imports.iter());
index 51698437a305b8916ff185846812f5d0f3bcb036..c7be9e2123512cae236c673adf01cec411436b32 100644 (file)
@@ -60,6 +60,17 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
             ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
                 self.check_def_id(item, data.principal_def_id().unwrap());
             }
+            ty::Dynamic(..) => {
+                struct_span_err!(
+                    self.tcx.sess,
+                    ty.span,
+                    E0785,
+                    "cannot define inherent `impl` for a dyn auto trait"
+                )
+                .span_label(ty.span, "impl requires at least one non-auto trait")
+                .note("define and implement a new trait or type instead")
+                .emit();
+            }
             ty::Bool => {
                 self.check_primitive_impl(
                     item.def_id,
index 03a9fe01795f5c70a76735257e4993d106b6effc..7ac26a31872df4792b80aeb08af9b3658cae035f 100644 (file)
@@ -195,7 +195,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) {
 }
 
 pub fn check_coherence(tcx: TyCtxt<'_>) {
-    for &trait_def_id in tcx.hir().krate().trait_impls.keys() {
+    for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
         tcx.ensure().coherent_trait(trait_def_id);
     }
 
index 1c6fd5983cb59f49256980ead01bf435e530b101..64120510e5624a5c7fbed86eb89d7250d790d4e4 100644 (file)
@@ -68,6 +68,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
+        default_anon_const_substs: type_of::default_anon_const_substs,
         type_of: type_of::type_of,
         item_bounds: item_bounds::item_bounds,
         explicit_item_bounds: item_bounds::explicit_item_bounds,
@@ -364,10 +365,6 @@ fn item_def_id(&self) -> Option<DefId> {
         Some(self.item_def_id)
     }
 
-    fn default_constness_for_trait_bounds(&self) -> hir::Constness {
-        self.node().constness_for_typeck()
-    }
-
     fn get_type_parameter_bounds(
         &self,
         span: Span,
@@ -663,7 +660,6 @@ fn type_parameter_bounds_in_generics(
         only_self_bounds: OnlySelfBounds,
         assoc_name: Option<Ident>,
     ) -> Vec<(ty::Predicate<'tcx>, Span)> {
-        let constness = self.default_constness_for_trait_bounds();
         let from_ty_params = ast_generics
             .params
             .iter()
@@ -676,7 +672,7 @@ fn type_parameter_bounds_in_generics(
                 Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
                 None => true,
             })
-            .flat_map(|b| predicates_from_bound(self, ty, b, constness));
+            .flat_map(|b| predicates_from_bound(self, ty, b));
 
         let from_where_clauses = ast_generics
             .where_clause
@@ -702,7 +698,7 @@ fn type_parameter_bounds_in_generics(
                     })
                     .filter_map(move |b| bt.map(|bt| (bt, b)))
             })
-            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness));
+            .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
 
         from_ty_params.chain(from_where_clauses).collect()
     }
@@ -750,6 +746,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
         // These don't define types.
         hir::ItemKind::ExternCrate(_)
         | hir::ItemKind::Use(..)
+        | hir::ItemKind::Macro(_)
         | hir::ItemKind::Mod(_)
         | hir::ItemKind::GlobalAsm(_) => {}
         hir::ItemKind::ForeignMod { items, .. } => {
@@ -1492,7 +1489,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 }
 
                 // HACK(eddyb) this provides the correct generics when
-                // `feature(const_generics)` is enabled, so that const expressions
+                // `feature(generic_const_expressions)` is enabled, so that const expressions
                 // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
                 //
                 // Note that we do not supply the parent generics when using
@@ -2005,7 +2002,16 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
         // prove that the trait applies to the types that were
         // used, and adding the predicate into this list ensures
         // that this is done.
-        let span = tcx.sess.source_map().guess_head_span(tcx.def_span(def_id));
+        let mut span = tcx.def_span(def_id);
+        if tcx.sess.source_map().is_local_span(span) {
+            // `guess_head_span` reads the actual source file from
+            // disk to try to determine the 'head' snippet of the span.
+            // Don't do this for a span that comes from a file outside
+            // of our crate, since this would make our query output
+            // (and overall crate metadata) dependent on the
+            // *current* state of an external file.
+            span = tcx.sess.source_map().guess_head_span(span);
+        }
         result.predicates =
             tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
                 ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
@@ -2030,7 +2036,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     let mut is_default_impl_trait = None;
 
     let icx = ItemCtxt::new(tcx, def_id);
-    let constness = icx.default_constness_for_trait_bounds();
 
     const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty();
 
@@ -2226,8 +2231,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                     match bound {
                         hir::GenericBound::Trait(poly_trait_ref, modifier) => {
                             let constness = match modifier {
-                                hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
-                                hir::TraitBoundModifier::None => constness,
+                                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
+                                hir::TraitBoundModifier::MaybeConst => {
+                                    ty::BoundConstness::ConstIfConst
+                                }
                                 // We ignore `where T: ?Sized`, it is already part of
                                 // type parameter `T`.
                                 hir::TraitBoundModifier::Maybe => continue,
@@ -2302,7 +2309,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
         }
     }
 
-    if tcx.features().const_evaluatable_checked {
+    if tcx.features().generic_const_exprs {
         predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
     }
 
@@ -2320,7 +2327,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
             tcx,
             &mut predicates,
             trait_ref,
-            &mut cgp::parameters_for_impl(self_ty, trait_ref),
+            &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
         );
     }
 
@@ -2355,7 +2362,7 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
                 assert_eq!(uv.promoted, None);
                 let span = self.tcx.hir().span(c.hir_id);
                 self.preds.insert((
-                    ty::PredicateKind::ConstEvaluatable(uv.def, uv.substs).to_predicate(self.tcx),
+                    ty::PredicateKind::ConstEvaluatable(uv.shrink()).to_predicate(self.tcx),
                     span,
                 ));
             }
@@ -2490,14 +2497,13 @@ fn predicates_from_bound<'tcx>(
     astconv: &dyn AstConv<'tcx>,
     param_ty: Ty<'tcx>,
     bound: &'tcx hir::GenericBound<'tcx>,
-    constness: hir::Constness,
 ) -> Vec<(ty::Predicate<'tcx>, Span)> {
     match *bound {
         hir::GenericBound::Trait(ref tr, modifier) => {
             let constness = match modifier {
                 hir::TraitBoundModifier::Maybe => return vec![],
-                hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
-                hir::TraitBoundModifier::None => constness,
+                hir::TraitBoundModifier::MaybeConst => ty::BoundConstness::ConstIfConst,
+                hir::TraitBoundModifier::None => ty::BoundConstness::NotConst,
             };
 
             let mut bounds = Bounds::default();
index e63c3346e02b1dfc5a4a2f3ae53e8f45cb6f9286..7f9afaae0eaa2675f8273aaf32af2ee7e9c5a53b 100644 (file)
@@ -7,7 +7,7 @@
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::{HirId, Node};
 use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
 use rustc_span::symbol::Ident;
@@ -274,6 +274,31 @@ fn get_path_containing_arg_in_pat<'hir>(
     arg_path
 }
 
+pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
+    let generics = tcx.generics_of(def_id);
+    if let Some(parent) = generics.parent {
+        // This is the reason we bother with having optional anon const substs.
+        //
+        // In the future the substs of an anon const will depend on its parents predicates
+        // at which point eagerly looking at them will cause a query cycle.
+        //
+        // So for now this is only an assurance that this approach won't cause cycle errors in
+        // the future.
+        let _cycle_check = tcx.predicates_of(parent);
+    }
+
+    let substs = InternalSubsts::identity_for_item(tcx, def_id);
+    // We only expect substs with the following type flags as default substs.
+    //
+    // Getting this wrong can lead to ICE and unsoundness, so we assert it here.
+    for arg in substs.iter() {
+        let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
+            | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE;
+        assert!(!arg.has_type_flags(!allowed_flags));
+    }
+    substs
+}
+
 pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
     let def_id = def_id.expect_local();
     use rustc_hir::*;
@@ -402,6 +427,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                 }
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
+                | ItemKind::Macro(..)
                 | ItemKind::Mod(..)
                 | ItemKind::ForeignMod { .. }
                 | ItemKind::GlobalAsm(..)
@@ -446,13 +472,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             }
         }
 
-        Node::AnonConst(_) => {
-            if let Some(param) = tcx.opt_const_param_of(def_id) {
-                // We defer to `type_of` of the corresponding parameter
-                // for generic arguments.
-                return tcx.type_of(param);
-            }
+        Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => {
+            // We defer to `type_of` of the corresponding parameter
+            // for generic arguments.
+            tcx.type_of(param)
+        }
 
+        Node::AnonConst(_) => {
             let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
             match parent_node {
                 Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
@@ -665,7 +691,7 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     debug!("find_opaque_ty_constraints: scope={:?}", scope);
 
     if scope == hir::CRATE_HIR_ID {
-        intravisit::walk_crate(&mut locator, tcx.hir().krate());
+        tcx.hir().walk_toplevel_module(&mut locator);
     } else {
         debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
         match tcx.hir().get(scope) {
index 529de1a2874841b6055b333fb6f2a240cc0a163f..9b6f0be47caf5898e480540d4ffa14d2954a57f6 100644 (file)
@@ -27,12 +27,13 @@ fn from(param: ty::ParamConst) -> Self {
 
 /// Returns the set of parameters constrained by the impl header.
 pub fn parameters_for_impl<'tcx>(
+    tcx: TyCtxt<'tcx>,
     impl_self_ty: Ty<'tcx>,
     impl_trait_ref: Option<ty::TraitRef<'tcx>>,
 ) -> FxHashSet<Parameter> {
     let vec = match impl_trait_ref {
-        Some(tr) => parameters_for(&tr, false),
-        None => parameters_for(&impl_self_ty, false),
+        Some(tr) => parameters_for(tcx, &tr, false),
+        None => parameters_for(tcx, &impl_self_ty, false),
     };
     vec.into_iter().collect()
 }
@@ -43,20 +44,26 @@ pub fn parameters_for_impl<'tcx>(
 /// of parameters whose values are needed in order to constrain `ty` - these
 /// differ, with the latter being a superset, in the presence of projections.
 pub fn parameters_for<'tcx>(
+    tcx: TyCtxt<'tcx>,
     t: &impl TypeFoldable<'tcx>,
     include_nonconstraining: bool,
 ) -> Vec<Parameter> {
-    let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
+    let mut collector = ParameterCollector { tcx, parameters: vec![], include_nonconstraining };
     t.visit_with(&mut collector);
     collector.parameters
 }
 
-struct ParameterCollector {
+struct ParameterCollector<'tcx> {
+    tcx: TyCtxt<'tcx>,
     parameters: Vec<Parameter>,
     include_nonconstraining: bool,
 }
 
-impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
+impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.tcx)
+    }
+
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *t.kind() {
             ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
@@ -198,12 +205,12 @@ pub fn setup_constraining_predicates<'tcx>(
                 //     `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
                 // Then the projection only applies if `T` is known, but it still
                 // does not determine `U`.
-                let inputs = parameters_for(&projection.projection_ty, true);
+                let inputs = parameters_for(tcx, &projection.projection_ty, true);
                 let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(&p));
                 if !relies_only_on_inputs {
                     continue;
                 }
-                input_parameters.extend(parameters_for(&projection.ty, false));
+                input_parameters.extend(parameters_for(tcx, &projection.ty, false));
             } else {
                 continue;
             }
index 77834feb9ad55eef02afaf16747839f6a1114c2e..ba70006fe96b3bb7a918bbcde28f049addbd7ec0 100644 (file)
@@ -2,6 +2,7 @@
 //! normal visitor, which just walks the entire body in one shot, the
 //! `ExprUseVisitor` determines how expressions are being used.
 
+use hir::def::DefKind;
 // Export these here so that Clippy can use them.
 pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
 
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::ProjectionKind;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, adjustment, TyCtxt};
+use rustc_middle::ty::{self, adjustment, AdtKind, Ty, TyCtxt};
 use rustc_target::abi::VariantIdx;
 use std::iter;
 
 use crate::mem_categorization as mc;
 
-///////////////////////////////////////////////////////////////////////////
-// The Delegate trait
-
 /// This trait defines the callbacks you can expect to receive when
 /// employing the ExprUseVisitor.
 pub trait Delegate<'tcx> {
-    // The value found at `place` is moved, depending
-    // on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
-    //
-    // Use of a `Copy` type in a ByValue context is considered a use
-    // by `ImmBorrow` and `borrow` is called instead. This is because
-    // a shared borrow is the "minimum access" that would be needed
-    // to perform a copy.
-    //
-    //
-    // The parameter `diag_expr_id` indicates the HIR id that ought to be used for
-    // diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
-    // id will be the id of the expression `expr` but the place itself will have
-    // the id of the binding in the pattern `pat`.
+    /// The value found at `place` is moved, depending
+    /// on `mode`. Where `diag_expr_id` is the id used for diagnostics for `place`.
+    ///
+    /// Use of a `Copy` type in a ByValue context is considered a use
+    /// by `ImmBorrow` and `borrow` is called instead. This is because
+    /// a shared borrow is the "minimum access" that would be needed
+    /// to perform a copy.
+    ///
+    ///
+    /// The parameter `diag_expr_id` indicates the HIR id that ought to be used for
+    /// diagnostics. Around pattern matching such as `let pat = expr`, the diagnostic
+    /// id will be the id of the expression `expr` but the place itself will have
+    /// the id of the binding in the pattern `pat`.
     fn consume(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: hir::HirId);
 
-    // The value found at `place` is being borrowed with kind `bk`.
-    // `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
+    /// The value found at `place` is being borrowed with kind `bk`.
+    /// `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
     fn borrow(
         &mut self,
         place_with_id: &PlaceWithHirId<'tcx>,
@@ -50,44 +48,47 @@ fn borrow(
         bk: ty::BorrowKind,
     );
 
-    // The path at `assignee_place` is being assigned to.
-    // `diag_expr_id` is the id used for diagnostics (see `consume` for more details).
+    /// The path at `assignee_place` is being assigned to.
+    /// `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 `place` should be a fake read because of specified `cause`.
+    /// 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);
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 enum ConsumeMode {
-    Copy, // reference to x where x has a type that copies
-    Move, // reference to x where x has a type that moves
+    /// reference to x where x has a type that copies
+    Copy,
+    /// reference to x where x has a type that moves
+    Move,
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MutateMode {
     Init,
-    JustWrite,    // x = y
-    WriteAndRead, // x += y
+    /// Example: `x = y`
+    JustWrite,
+    /// Example: `x += y`
+    WriteAndRead,
 }
 
-///////////////////////////////////////////////////////////////////////////
-// The ExprUseVisitor type
-//
-// This is the code that actually walks the tree.
+/// The ExprUseVisitor type
+///
+/// This is the code that actually walks the tree.
 pub struct ExprUseVisitor<'a, 'tcx> {
     mc: mc::MemCategorizationContext<'a, 'tcx>,
     body_owner: LocalDefId,
     delegate: &'a mut dyn Delegate<'tcx>,
 }
 
-// If the MC results in an error, it's because the type check
-// failed (or will fail, when the error is uncovered and reported
-// during writeback). In this case, we just ignore this part of the
-// code.
-//
-// Note that this macro appears similar to try!(), but, unlike try!(),
-// it does not propagate the error.
+/// If the MC results in an error, it's because the type check
+/// failed (or will fail, when the error is uncovered and reported
+/// during writeback). In this case, we just ignore this part of the
+/// code.
+///
+/// Note that this macro appears similar to try!(), but, unlike try!(),
+/// it does not propagate the error.
 macro_rules! return_if_err {
     ($inp: expr) => {
         match $inp {
@@ -120,9 +121,8 @@ pub fn new(
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     pub fn consume_body(&mut self, body: &hir::Body<'_>) {
-        debug!("consume_body(body={:?})", body);
-
         for param in body.params {
             let param_ty = return_if_err!(self.mc.pat_ty_adjusted(&param.pat));
             debug!("consume_body: param_ty = {:?}", param_ty);
@@ -252,28 +252,37 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                                     needs_to_be_read = true;
                                 }
                             }
-                            PatKind::TupleStruct(..)
-                            | PatKind::Path(..)
-                            | PatKind::Struct(..)
-                            | PatKind::Tuple(..) => {
-                                // If the PatKind is a TupleStruct, Path, Struct or Tuple then we want to check
-                                // whether the Variant is a MultiVariant or a SingleVariant. We only want
-                                // to borrow discr if it is a MultiVariant.
-                                // If it is a SingleVariant and creates a binding we will handle that when
-                                // this callback gets called again.
-
-                                // Get the type of the Place after all projections have been applied
-                                let place_ty = place.place.ty();
-
-                                if let ty::Adt(def, _) = place_ty.kind() {
-                                    if def.variants.len() > 1 {
+                            PatKind::Path(qpath) => {
+                                // A `Path` pattern is just a name like `Foo`. This is either a
+                                // named constant or else it refers to an ADT variant
+
+                                let res = self.mc.typeck_results.qpath_res(qpath, pat.hir_id);
+                                match res {
+                                    Res::Def(DefKind::Const, _)
+                                    | Res::Def(DefKind::AssocConst, _) => {
+                                        // Named constants have to be equated with the value
+                                        // being matched, so that's a read of the value being matched.
+                                        //
+                                        // FIXME: We don't actually  reads for ZSTs.
                                         needs_to_be_read = true;
                                     }
-                                } else {
-                                    // If it is not ty::Adt, then it should be read
-                                    needs_to_be_read = true;
+                                    _ => {
+                                        // Otherwise, this is a struct/enum variant, and so it's
+                                        // only a read if we need to read the discriminant.
+                                        needs_to_be_read |= is_multivariant_adt(place.place.ty());
+                                    }
                                 }
                             }
+                            PatKind::TupleStruct(..) | PatKind::Struct(..) | PatKind::Tuple(..) => {
+                                // For `Foo(..)`, `Foo { ... }` and `(...)` patterns, check if we are matching
+                                // against a multivariant enum or struct. In that case, we have to read
+                                // the discriminant. Otherwise this kind of pattern doesn't actually
+                                // read anything (we'll get invoked for the `...`, which may indeed
+                                // perform some reads).
+
+                                let place_ty = place.place.ty();
+                                needs_to_be_read |= is_multivariant_adt(place_ty);
+                            }
                             PatKind::Lit(_) | PatKind::Range(..) => {
                                 // If the PatKind is a Lit or a Range then we want
                                 // to borrow discr.
@@ -335,12 +344,8 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. }
                         | hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr),
-                        hir::InlineAsmOperand::Out { expr, .. } => {
-                            if let Some(expr) = expr {
-                                self.mutate_expr(expr);
-                            }
-                        }
-                        hir::InlineAsmOperand::InOut { expr, .. } => {
+                        hir::InlineAsmOperand::Out { expr: Some(expr), .. }
+                        | hir::InlineAsmOperand::InOut { expr, .. } => {
                             self.mutate_expr(expr);
                         }
                         hir::InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
@@ -349,7 +354,8 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
                                 self.mutate_expr(out_expr);
                             }
                         }
-                        hir::InlineAsmOperand::Const { .. } => {}
+                        hir::InlineAsmOperand::Out { expr: None, .. }
+                        | hir::InlineAsmOperand::Const { .. } => {}
                     }
                 }
             }
@@ -531,9 +537,9 @@ fn walk_struct_expr(
         self.walk_expr(with_expr);
     }
 
-    // Invoke the appropriate delegate calls for anything that gets
-    // consumed or borrowed as part of the automatic adjustment
-    // process.
+    /// Invoke the appropriate delegate calls for anything that gets
+    /// consumed or borrowed as part of the automatic adjustment
+    /// process.
     fn walk_adjustment(&mut self, expr: &hir::Expr<'_>) {
         let adjustments = self.mc.typeck_results.expr_adjustments(expr);
         let mut place_with_id = return_if_err!(self.mc.cat_expr_unadjusted(expr));
@@ -837,3 +843,22 @@ fn delegate_consume<'a, 'tcx>(
         }
     }
 }
+
+fn is_multivariant_adt(ty: Ty<'tcx>) -> bool {
+    if let ty::Adt(def, _) = ty.kind() {
+        // Note that if a non-exhaustive SingleVariant is defined in another crate, we need
+        // to assume that more cases will be added to the variant in the future. This mean
+        // that we should handle non-exhaustive SingleVariant the same way we would handle
+        // a MultiVariant.
+        // If the variant is not local it must be defined in another crate.
+        let is_non_exhaustive = match def.adt_kind() {
+            AdtKind::Struct | AdtKind::Union => {
+                def.non_enum_variant().is_field_list_non_exhaustive()
+            }
+            AdtKind::Enum => def.is_variant_list_non_exhaustive(),
+        };
+        def.variants.len() > 1 || (!def.did.is_local() && is_non_exhaustive)
+    } else {
+        false
+    }
+}
index 1240946860573bf88e96ad26651ae0fd156a399e..194c4efdbb05888fb8b677e1361f06e22f0b0d7b 100644 (file)
@@ -119,7 +119,7 @@ fn enforce_impl_params_are_constrained(
     let impl_predicates = tcx.predicates_of(impl_def_id);
     let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
 
-    let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
+    let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
     cgp::identify_constrained_generic_params(
         tcx,
         impl_predicates,
@@ -136,7 +136,7 @@ fn enforce_impl_params_are_constrained(
             match item.kind {
                 ty::AssocKind::Type => {
                     if item.defaultness.has_value() {
-                        cgp::parameters_for(&tcx.type_of(def_id), true)
+                        cgp::parameters_for(tcx, &tcx.type_of(def_id), true)
                     } else {
                         Vec::new()
                     }
index e148370a03610f3389e6716b7d7b67e5e32ea1a3..8ecd6034ad6951c1d7dd8a5908eb896c92169e2e 100644 (file)
@@ -68,7 +68,6 @@
 use crate::constrained_generic_params as cgp;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
@@ -207,15 +206,15 @@ fn unconstrained_parent_impl_substs<'tcx>(
                 continue;
             }
 
-            unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
+            unconstrained_parameters.extend(cgp::parameters_for(tcx, &projection_ty, true));
 
-            for param in cgp::parameters_for(&projected_ty, false) {
+            for param in cgp::parameters_for(tcx, &projected_ty, false) {
                 if !unconstrained_parameters.contains(&param) {
                     constrained_params.insert(param.0);
                 }
             }
 
-            unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
+            unconstrained_parameters.extend(cgp::parameters_for(tcx, &projected_ty, true));
         }
     }
 
@@ -249,7 +248,7 @@ fn check_duplicate_params<'tcx>(
     parent_substs: &Vec<GenericArg<'tcx>>,
     span: Span,
 ) {
-    let mut base_params = cgp::parameters_for(parent_substs, true);
+    let mut base_params = cgp::parameters_for(tcx, parent_substs, true);
     base_params.sort_by_key(|param| param.0);
     if let (_, [duplicate, ..]) = base_params.partition_dedup() {
         let param = impl1_substs[duplicate.0 as usize];
@@ -363,12 +362,12 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
     match predicate.kind().skip_binder() {
         // Global predicates are either always true or always false, so we
         // are fine to specialize on.
-        _ if predicate.is_global() => (),
+        _ if predicate.is_global(tcx) => (),
         // We allow specializing on explicitly marked traits with no associated
         // items.
         ty::PredicateKind::Trait(ty::TraitPredicate {
             trait_ref,
-            constness: hir::Constness::NotConst,
+            constness: ty::BoundConstness::NotConst,
         }) => {
             if !matches!(
                 trait_predicate_kind(tcx, predicate),
@@ -399,7 +398,7 @@ fn trait_predicate_kind<'tcx>(
     match predicate.kind().skip_binder() {
         ty::PredicateKind::Trait(ty::TraitPredicate {
             trait_ref,
-            constness: hir::Constness::NotConst,
+            constness: ty::BoundConstness::NotConst,
         }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
         ty::PredicateKind::Trait(_)
         | ty::PredicateKind::RegionOutlives(_)
index 61631f3b14bb17ae0c79886c89b3fa635dae9a51..749f681e92ed174750f70420ff063b70ccb10a41 100644 (file)
@@ -60,6 +60,7 @@
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
+#![feature(if_let_guard)]
 #![feature(in_band_lifetimes)]
 #![feature(is_sorted)]
 #![feature(iter_zip)]
@@ -68,6 +69,7 @@
 #![feature(never_type)]
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -546,7 +548,7 @@ pub fn hir_trait_to_predicates<'tcx>(
         &item_cx,
         hir_trait,
         DUMMY_SP,
-        hir::Constness::NotConst,
+        ty::BoundConstness::NotConst,
         self_ty,
         &mut bounds,
         true,
index ccf0fb7273837b57577ee97fe91f677e4557aab2..0e96601d89fd8d91204a0ee3af63b69c60fbd0c0 100644 (file)
@@ -114,7 +114,18 @@ fn insert_required_predicates_to_be_wf<'tcx>(
     required_predicates: &mut RequiredPredicates<'tcx>,
     explicit_map: &mut ExplicitPredicatesMap<'tcx>,
 ) {
-    for arg in field_ty.walk() {
+    // We must not look into the default substs of consts
+    // as computing those depends on the results of `predicates_of`.
+    //
+    // Luckily the only types contained in default substs are type
+    // parameters which don't matter here.
+    //
+    // FIXME(adt_const_params): Once complex const parameter types
+    // are allowed, this might be incorrect. I think that we will still be
+    // fine, as all outlives relations of the const param types should also
+    // be part of the adt containing it, but we should still both update the
+    // documentation and add some tests for this.
+    for arg in field_ty.walk_ignoring_default_const_substs() {
         let ty = match arg.unpack() {
             GenericArgKind::Type(ty) => ty,
 
@@ -306,7 +317,7 @@ pub fn check_explicit_predicates<'tcx>(
         // 'b`.
         if let Some(self_ty) = ignored_self_ty {
             if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() {
-                if ty.walk().any(|arg| arg == self_ty.into()) {
+                if ty.walk(tcx).any(|arg| arg == self_ty.into()) {
                     debug!("skipping self ty = {:?}", &ty);
                     continue;
                 }
index 4b649e43371dee25eaae95c3758662305ea22366..70a838a35f9d202b0af56357af0a4da9382d0536 100644 (file)
@@ -233,9 +233,7 @@ fn clone_subtree<'a, K: Clone, V: Clone>(
         }
 
         if self.is_empty() {
-            // Ideally we'd call `BTreeMap::new` here, but that has the `K:
-            // Ord` constraint, which this method lacks.
-            BTreeMap { root: None, length: 0 }
+            BTreeMap::new()
         } else {
             clone_subtree(self.root.as_ref().unwrap().reborrow()) // unwrap succeeds because not empty
         }
@@ -499,10 +497,7 @@ impl<K, V> BTreeMap<K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
-    pub const fn new() -> BTreeMap<K, V>
-    where
-        K: Ord,
-    {
+    pub const fn new() -> BTreeMap<K, V> {
         BTreeMap { root: None, length: 0 }
     }
 
@@ -522,7 +517,7 @@ pub const fn new() -> BTreeMap<K, V>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
-        *self = BTreeMap { root: None, length: 0 };
+        *self = BTreeMap::new();
     }
 
     /// Returns a reference to the value corresponding to the key.
@@ -1957,7 +1952,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<K: Ord, V> Default for BTreeMap<K, V> {
+impl<K, V> Default for BTreeMap<K, V> {
     /// Creates an empty `BTreeMap`.
     fn default() -> BTreeMap<K, V> {
         BTreeMap::new()
index 17e538483431ca0573317c64f98248920eeb7f7a..a99d6c49ab7b372b286d9d901985fe61129d5082 100644 (file)
@@ -1745,7 +1745,7 @@ fn vacant_entry<T: Send + Ord + Default>(v: &mut BTreeMap<T, T>) -> impl Send +
     }
 }
 
-#[allow(dead_code)]
+#[test]
 fn test_ord_absence() {
     fn map<K>(mut map: BTreeMap<K, ()>) {
         map.is_empty();
@@ -1784,6 +1784,12 @@ fn map_debug<K: Debug>(mut map: BTreeMap<K, ()>) {
     fn map_clone<K: Clone>(mut map: BTreeMap<K, ()>) {
         map.clone_from(&map.clone());
     }
+
+    #[derive(Debug, Clone)]
+    struct NonOrd;
+    map(BTreeMap::<NonOrd, _>::new());
+    map_debug(BTreeMap::<NonOrd, _>::new());
+    map_clone(BTreeMap::<NonOrd, _>::default());
 }
 
 #[test]
index 0c268ad32b2612b4d0cd070ca99e2fbf2807e050..ff0db22e0cc2d48519bbfac8ffb37f4752cce3a0 100644 (file)
@@ -246,10 +246,7 @@ impl<T> BTreeSet<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
-    pub const fn new() -> BTreeSet<T>
-    where
-        T: Ord,
-    {
+    pub const fn new() -> BTreeSet<T> {
         BTreeSet { map: BTreeMap::new() }
     }
 
@@ -1192,7 +1189,7 @@ fn extend_one(&mut self, &elem: &'a T) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Ord> Default for BTreeSet<T> {
+impl<T> Default for BTreeSet<T> {
     /// Creates an empty `BTreeSet`.
     fn default() -> BTreeSet<T> {
         BTreeSet::new()
index 5d590a26281d2b993d38aea9e7e6e1ca0eba46eb..0a87ae12d61a59a34f957903aef3d0958010b9e6 100644 (file)
@@ -607,7 +607,7 @@ fn union<T: Send + Sync + Ord>(v: &BTreeSet<T>) -> impl Send + '_ {
     }
 }
 
-#[allow(dead_code)]
+#[test]
 fn test_ord_absence() {
     fn set<K>(mut set: BTreeSet<K>) {
         set.is_empty();
@@ -626,6 +626,12 @@ fn set_debug<K: Debug>(set: BTreeSet<K>) {
     fn set_clone<K: Clone>(mut set: BTreeSet<K>) {
         set.clone_from(&set.clone());
     }
+
+    #[derive(Debug, Clone)]
+    struct NonOrd;
+    set(BTreeSet::<NonOrd>::new());
+    set_debug(BTreeSet::<NonOrd>::new());
+    set_clone(BTreeSet::<NonOrd>::default());
 }
 
 #[test]
index 7aa24ff4afaeef919eb4c745b9d1e41da917dbdb..9d45c5082db434cb4a13cf63776f3e529aee1b39 100644 (file)
@@ -300,7 +300,10 @@ fn detach_all_nodes(mut self) -> Option<(NonNull<Node<T>>, NonNull<Node<T>>, usi
         let tail = self.tail.take();
         let len = mem::replace(&mut self.len, 0);
         if let Some(head) = head {
-            let tail = tail.unwrap_or_else(|| unsafe { core::hint::unreachable_unchecked() });
+            // SAFETY: In a LinkedList, either both the head and tail are None because
+            // the list is empty, or both head and tail are Some because the list is populated.
+            // Since we have verified the head is Some, we are sure the tail is Some too.
+            let tail = unsafe { tail.unwrap_unchecked() };
             Some((head, tail, len))
         } else {
             None
index 0d442011921ba7bb5516058d21f6facbb76a31a6..4e31df8b4b8c23a65c5b3b807f67b6b36ec6ae5a 100644 (file)
@@ -117,12 +117,12 @@ fn from(kind: TryReserveErrorKind) -> Self {
     }
 }
 
-#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
-impl From<LayoutError> for TryReserveError {
+#[unstable(feature = "try_reserve_kind", reason = "new API", issue = "48043")]
+impl From<LayoutError> for TryReserveErrorKind {
     /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`].
     #[inline]
     fn from(_: LayoutError) -> Self {
-        TryReserveErrorKind::CapacityOverflow.into()
+        TryReserveErrorKind::CapacityOverflow
     }
 }
 
index 3caada06f6b58d33128685ea8fb0ca32184c3b4f..be21018512d8bbe9c158bf5f1ee7640a4175aa1d 100644 (file)
@@ -323,7 +323,7 @@ fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
     pub fn reserve(&mut self, len: usize, additional: usize) {
         // Callers expect this function to be very cheap when there is already sufficient capacity.
         // Therefore, we move all the resizing and error-handling logic from grow_amortized and
-        // handle_reserve behind a call, while making sure that the this function is likely to be
+        // handle_reserve behind a call, while making sure that this function is likely to be
         // inlined as just a comparison and a call if the comparison fails.
         #[cold]
         fn do_reserve_and_handle<T, A: Allocator>(
index 0b3079fa59db602ace6aea67c1297380c36bf886..0814652a5d47d595822ed1a7492d2ad81f97b60c 100644 (file)
@@ -1011,7 +1011,7 @@ fn is_unique(this: &Self) -> bool {
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
-    /// the inner value when there are other pointers.
+    /// the inner value when there are other `Rc` pointers.
     ///
     /// [make_mut]: Rc::make_mut
     /// [clone]: Clone::clone
@@ -1100,10 +1100,12 @@ impl<T: Clone> Rc<T> {
     /// [`clone`] the inner value to a new allocation to ensure unique ownership.  This is also
     /// referred to as clone-on-write.
     ///
-    /// If there are no other `Rc` pointers to this allocation, then [`Weak`]
-    /// pointers to this allocation will be disassociated.
+    /// However, if there are no other `Rc` pointers to this allocation, but some [`Weak`]
+    /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
+    /// be cloned.
     ///
-    /// See also [`get_mut`], which will fail rather than cloning.
+    /// See also [`get_mut`], which will fail rather than cloning the inner value
+    /// or diassociating [`Weak`] pointers.
     ///
     /// [`clone`]: Clone::clone
     /// [`get_mut`]: Rc::get_mut
@@ -1115,11 +1117,11 @@ impl<T: Clone> Rc<T> {
     ///
     /// let mut data = Rc::new(5);
     ///
-    /// *Rc::make_mut(&mut data) += 1;        // Won't clone anything
-    /// let mut other_data = Rc::clone(&data);    // Won't clone inner data
-    /// *Rc::make_mut(&mut data) += 1;        // Clones inner data
-    /// *Rc::make_mut(&mut data) += 1;        // Won't clone anything
-    /// *Rc::make_mut(&mut other_data) *= 2;  // Won't clone anything
+    /// *Rc::make_mut(&mut data) += 1;         // Won't clone anything
+    /// let mut other_data = Rc::clone(&data); // Won't clone inner data
+    /// *Rc::make_mut(&mut data) += 1;         // Clones inner data
+    /// *Rc::make_mut(&mut data) += 1;         // Won't clone anything
+    /// *Rc::make_mut(&mut other_data) *= 2;   // Won't clone anything
     ///
     /// // Now `data` and `other_data` point to different allocations.
     /// assert_eq!(*data, 8);
@@ -1743,7 +1745,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_for_ptrs", since = "1.6.0")]
 impl<T> From<T> for Rc<T> {
-    /// Converts a generic type `T` into a `Rc<T>`
+    /// Converts a generic type `T` into an `Rc<T>`
     ///
     /// The conversion allocates on the heap and moves `t`
     /// from the stack into it.
index 3183a6db410b8bddbf6329a9f21531f508be20d8..a066e0b49e25c4505381f7d83e037bd8e24e4d86 100644 (file)
@@ -1346,18 +1346,19 @@ impl<T: ?Sized> Receiver for Arc<T> {}
 impl<T: Clone> Arc<T> {
     /// Makes a mutable reference into the given `Arc`.
     ///
-    /// If there are other `Arc` or [`Weak`] pointers to the same allocation,
-    /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
-    /// to ensure unique ownership. This is also referred to as clone-on-write.
+    /// If there are other `Arc` pointers to the same allocation, then `make_mut` will
+    /// [`clone`] the inner value to a new allocation to ensure unique ownership.  This is also
+    /// referred to as clone-on-write.
     ///
-    /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates
-    /// any remaining `Weak` pointers.
+    /// However, if there are no other `Arc` pointers to this allocation, but some [`Weak`]
+    /// pointers, then the [`Weak`] pointers will be disassociated and the inner value will not
+    /// be cloned.
     ///
-    /// See also [`get_mut`][get_mut], which will fail rather than cloning.
+    /// See also [`get_mut`], which will fail rather than cloning the inner value
+    /// or diassociating [`Weak`] pointers.
     ///
-    /// [clone]: Clone::clone
-    /// [get_mut]: Arc::get_mut
-    /// [`Rc::make_mut`]: super::rc::Rc::make_mut
+    /// [`clone`]: Clone::clone
+    /// [`get_mut`]: Arc::get_mut
     ///
     /// # Examples
     ///
@@ -1376,6 +1377,23 @@ impl<T: Clone> Arc<T> {
     /// assert_eq!(*data, 8);
     /// assert_eq!(*other_data, 12);
     /// ```
+    ///
+    /// [`Weak`] pointers will be disassociated:
+    ///
+    /// ```
+    /// use std::sync::Arc;
+    ///
+    /// let mut data = Arc::new(75);
+    /// let weak = Arc::downgrade(&data);
+    ///
+    /// assert!(75 == *data);
+    /// assert!(75 == *weak.upgrade().unwrap());
+    ///
+    /// *Arc::make_mut(&mut data) += 1;
+    ///
+    /// assert!(76 == *data);
+    /// assert!(weak.upgrade().is_none());
+    /// ```
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "arc_unique", since = "1.4.0")]
@@ -1441,7 +1459,7 @@ impl<T: ?Sized> Arc<T> {
     /// mutate a shared value.
     ///
     /// See also [`make_mut`][make_mut], which will [`clone`][clone]
-    /// the inner value when there are other pointers.
+    /// the inner value when there are other `Arc` pointers.
     ///
     /// [make_mut]: Arc::make_mut
     /// [clone]: Clone::clone
index 6a83f5da87cc8f413348861bbb80e547cc2c7457..a38b5c471bf06cc63b546b28fa5e8c1a44836379 100644 (file)
@@ -35,11 +35,11 @@ fn box_clone_and_clone_from_equivalence() {
     }
 }
 
-/// This test might give a false positive in case the box realocates, but the alocator keeps the
-/// original pointer.
+/// This test might give a false positive in case the box reallocates,
+/// but the allocator keeps the original pointer.
 ///
-/// On the other hand it won't give a false negative, if it fails than the memory was definitely not
-/// reused
+/// On the other hand, it won't give a false negative: If it fails, then the
+/// memory was definitely not reused.
 #[test]
 fn box_clone_from_ptr_stability() {
     for size in (0..8).map(|i| 2usize.pow(i)) {
index da58ae92e112489516b49391f71bd1130f0b2f79..f448b3eb7c3000e611694fc018e0ca038faae4cb 100644 (file)
@@ -1,29 +1,5 @@
 // Test const functions in the library
 
-use core::cmp::Ordering;
-
-// FIXME remove this struct once we put `K: ?const Ord` on BTreeMap::new.
-#[derive(PartialEq, Eq, PartialOrd)]
-pub struct MyType;
-
-impl const Ord for MyType {
-    fn cmp(&self, _: &Self) -> Ordering {
-        Ordering::Equal
-    }
-
-    fn max(self, _: Self) -> Self {
-        Self
-    }
-
-    fn min(self, _: Self) -> Self {
-        Self
-    }
-
-    fn clamp(self, _: Self, _: Self) -> Self {
-        Self
-    }
-}
-
 pub const MY_VEC: Vec<usize> = Vec::new();
 pub const MY_VEC2: Vec<usize> = Default::default();
 
@@ -32,13 +8,13 @@ fn clamp(self, _: Self, _: Self) -> Self {
 
 use std::collections::{BTreeMap, BTreeSet};
 
-pub const MY_BTREEMAP: BTreeMap<MyType, MyType> = BTreeMap::new();
-pub const MAP: &'static BTreeMap<MyType, MyType> = &MY_BTREEMAP;
+pub const MY_BTREEMAP: BTreeMap<usize, usize> = BTreeMap::new();
+pub const MAP: &'static BTreeMap<usize, usize> = &MY_BTREEMAP;
 pub const MAP_LEN: usize = MAP.len();
 pub const MAP_IS_EMPTY: bool = MAP.is_empty();
 
-pub const MY_BTREESET: BTreeSet<MyType> = BTreeSet::new();
-pub const SET: &'static BTreeSet<MyType> = &MY_BTREESET;
+pub const MY_BTREESET: BTreeSet<usize> = BTreeSet::new();
+pub const SET: &'static BTreeSet<usize> = &MY_BTREESET;
 pub const SET_LEN: usize = SET.len();
 pub const SET_IS_EMPTY: bool = SET.is_empty();
 
index 77c52e51abb2e2b149538199f5d53033ecfc441f..ecdbf09881985a9ee7e4ab997c3750994a6142cd 100644 (file)
@@ -37,7 +37,7 @@ impl<T, const N: usize> IntoIter<T, N> {
     /// Creates a new iterator over the given `array`.
     ///
     /// *Note*: this method might be deprecated in the future,
-    /// after [`IntoIterator` is implemented for arrays][array-into-iter].
+    /// since [`IntoIterator`] is now implemented for arrays.
     ///
     /// # Examples
     ///
@@ -48,8 +48,13 @@ impl<T, const N: usize> IntoIter<T, N> {
     ///     // The type of `value` is an `i32` here, instead of `&i32`
     ///     let _: i32 = value;
     /// }
+    ///
+    /// // Since Rust 1.53, arrays implement IntoIterator directly:
+    /// for value in [1, 2, 3, 4, 5] {
+    ///     // The type of `value` is an `i32` here, instead of `&i32`
+    ///     let _: i32 = value;
+    /// }
     /// ```
-    /// [array-into-iter]: https://github.com/rust-lang/rust/pull/65819
     #[stable(feature = "array_value_iter", since = "1.51.0")]
     pub fn new(array: [T; N]) -> Self {
         // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
index 3c638e655dc91dd525e42c9fc2c101c89a7ab682..8c33a43ab330ebd4d847152d7e188cbb231afbb6 100644 (file)
@@ -396,7 +396,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     ///
     /// This method is particularly useful if combined with other methods, like
     /// [`map`](#method.map). This way, you can avoid moving the original
-    /// array if its elements are not `Copy`.
+    /// array if its elements are not [`Copy`].
     ///
     /// ```
     /// #![feature(array_methods)]
@@ -459,11 +459,8 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX));
     debug_assert!(N <= iter.size_hint().0);
 
-    match collect_into_array(iter) {
-        Some(array) => array,
-        // SAFETY: covered by the function contract.
-        None => unsafe { crate::hint::unreachable_unchecked() },
-    }
+    // SAFETY: covered by the function contract.
+    unsafe { collect_into_array(iter).unwrap_unchecked() }
 }
 
 /// Pulls `N` items from `iter` and returns them as an array. If the iterator
index dcafaae2f5b493a4a858462f589cc52ade71e76b..ca1c0ae759892466228d0f072e48a6da7da78df6 100644 (file)
@@ -2,7 +2,7 @@
 
 #[lang = "bool"]
 impl bool {
-    /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
+    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
     ///
     /// # Examples
     ///
@@ -18,7 +18,7 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
         if self { Some(t) } else { None }
     }
 
-    /// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
+    /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
     ///
     /// # Examples
     ///
index f0c934edf3977b0856671d8d10e5106a2927771a..2adf6a549e6417b94349752487b39f76257fa727 100644 (file)
@@ -576,6 +576,26 @@ pub fn as_slice_of_cells(&self) -> &[Cell<T>] {
     }
 }
 
+impl<T, const N: usize> Cell<[T; N]> {
+    /// Returns a `&[Cell<T>; N]` from a `&Cell<[T; N]>`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(as_array_of_cells)]
+    /// use std::cell::Cell;
+    ///
+    /// let mut array: [i32; 3] = [1, 2, 3];
+    /// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
+    /// let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
+    /// ```
+    #[unstable(feature = "as_array_of_cells", issue = "88248")]
+    pub fn as_array_of_cells(&self) -> &[Cell<T>; N] {
+        // SAFETY: `Cell<T>` has the same memory layout as `T`.
+        unsafe { &*(self as *const Cell<[T; N]> as *const [Cell<T>; N]) }
+    }
+}
+
 /// A mutable memory location with dynamically checked borrow rules
 ///
 /// See the [module-level documentation](self) for more.
@@ -1901,7 +1921,7 @@ pub fn get_mut(&mut self) -> &mut T {
     }
 
     /// Gets a mutable pointer to the wrapped value.
-    /// The difference to [`get`] is that this function accepts a raw pointer,
+    /// The difference from [`get`] is that this function accepts a raw pointer,
     /// which is useful to avoid the creation of temporary references.
     ///
     /// The result can be cast to a pointer of any kind.
@@ -1917,7 +1937,6 @@ pub fn get_mut(&mut self) -> &mut T {
     /// calling `get` would require creating a reference to uninitialized data:
     ///
     /// ```
-    /// #![feature(unsafe_cell_raw_get)]
     /// use std::cell::UnsafeCell;
     /// use std::mem::MaybeUninit;
     ///
@@ -1928,7 +1947,7 @@ pub fn get_mut(&mut self) -> &mut T {
     /// assert_eq!(uc.into_inner(), 5);
     /// ```
     #[inline(always)]
-    #[unstable(feature = "unsafe_cell_raw_get", issue = "66358")]
+    #[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")]
     pub const fn raw_get(this: *const Self) -> *mut T {
         // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
         // #[repr(transparent)]. This exploits libstd's special status, there is
index 0dadbdd1bd0543e4c08423b91c59363f8e777f7b..e6d3ac8f2d2c5d3637cb4fd144fc1572cedf691a 100644 (file)
@@ -96,7 +96,7 @@ pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::Into
     /// Converts a `u32` to a `char`.
     ///
     /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
-    /// `as`:
+    /// [`as`](keyword.as.html):
     ///
     /// ```
     /// let c = '💯';
@@ -372,7 +372,7 @@ pub fn to_digit(self, radix: u32) -> Option<u32> {
     /// println!("\\u{{2764}}");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
@@ -422,7 +422,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
     /// Returns an iterator that yields the literal escape code of a character
     /// as `char`s.
     ///
-    /// This will escape the characters similar to the `Debug` implementations
+    /// This will escape the characters similar to the [`Debug`](core::fmt::Debug) implementations
     /// of `str` or `char`.
     ///
     /// # Examples
@@ -448,7 +448,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
     /// println!("\\n");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
@@ -502,7 +502,7 @@ pub fn escape_debug(self) -> EscapeDebug {
     /// println!("\\\"");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('"'.escape_default().to_string(), "\\\"");
@@ -937,7 +937,7 @@ pub fn is_numeric(self) -> bool {
     /// println!("i\u{307}");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('C'.to_lowercase().to_string(), "c");
@@ -1002,7 +1002,7 @@ pub fn to_lowercase(self) -> ToLowercase {
     /// println!("SS");
     /// ```
     ///
-    /// Using `to_string`:
+    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('c'.to_uppercase().to_string(), "C");
@@ -1131,7 +1131,7 @@ pub const fn to_ascii_lowercase(&self) -> char {
 
     /// Checks that two values are an ASCII case-insensitive match.
     ///
-    /// Equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
+    /// Equivalent to <code>[to_ascii_lowercase]\(a) == [to_ascii_lowercase]\(b)</code>.
     ///
     /// # Examples
     ///
@@ -1144,6 +1144,8 @@ pub const fn to_ascii_lowercase(&self) -> char {
     /// assert!(upper_a.eq_ignore_ascii_case(&upper_a));
     /// assert!(!upper_a.eq_ignore_ascii_case(&lower_z));
     /// ```
+    ///
+    /// [to_ascii_lowercase]: #method.to_ascii_lowercase
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.52.0")]
     #[inline]
index 79610bb409d37c06b383ea7622452560b179ebf6..4e82b65539460eeaffeb71fe8839a79c93359548 100644 (file)
@@ -660,6 +660,18 @@ fn clone_from(&mut self, other: &Self) {
 /// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
 /// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering based on the top-to-bottom declaration order of the struct's members.
 /// When `derive`d on enums, variants are ordered by their top-to-bottom discriminant order.
+/// This means variants at the top are less than variants at the bottom.
+/// Here's an example:
+///
+/// ```
+/// #[derive(PartialEq, PartialOrd)]
+/// enum Size {
+///     Small,
+///     Large,
+/// }
+///
+/// assert!(Size::Small < Size::Large);
+/// ```
 ///
 /// ## Lexicographical comparison
 ///
index 1d75ac3d254bd641ff9d4783b3de73219920de38..aff789f2afa1486b1b25816b2d15ccb6c5510493 100644 (file)
@@ -402,7 +402,7 @@ pub fn estimated_capacity(&self) -> usize {
 
         if self.args.is_empty() {
             pieces_length
-        } else if self.pieces[0] == "" && pieces_length < 16 {
+        } else if !self.pieces.is_empty() && self.pieces[0].is_empty() && pieces_length < 16 {
             // If the format string starts with an argument,
             // don't preallocate anything, unless length
             // of pieces is significant.
@@ -1163,7 +1163,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
                 }
                 // SAFETY: arg and args.args come from the same Arguments,
                 // which guarantees the indexes are always within bounds.
-                unsafe { run(&mut formatter, arg, &args.args) }?;
+                unsafe { run(&mut formatter, arg, args.args) }?;
                 idx += 1;
             }
         }
@@ -1409,7 +1409,7 @@ pub fn pad(&mut self, s: &str) -> Result {
                 // we know that it can't panic. Use `get` + `unwrap_or` to avoid
                 // `unsafe` and otherwise don't emit any panic-related code
                 // here.
-                s.get(..i).unwrap_or(&s)
+                s.get(..i).unwrap_or(s)
             } else {
                 &s
             }
@@ -1421,16 +1421,21 @@ pub fn pad(&mut self, s: &str) -> Result {
             // If we're under the maximum length, and there's no minimum length
             // requirements, then we can just emit the string
             None => self.buf.write_str(s),
-            // If we're under the maximum width, check if we're over the minimum
-            // width, if so it's as easy as just emitting the string.
-            Some(width) if s.chars().count() >= width => self.buf.write_str(s),
-            // If we're under both the maximum and the minimum width, then fill
-            // up the minimum width with the specified string + some alignment.
             Some(width) => {
-                let align = rt::v1::Alignment::Left;
-                let post_padding = self.padding(width - s.chars().count(), align)?;
-                self.buf.write_str(s)?;
-                post_padding.write(self.buf)
+                let chars_count = s.chars().count();
+                // If we're under the maximum width, check if we're over the minimum
+                // width, if so it's as easy as just emitting the string.
+                if chars_count >= width {
+                    self.buf.write_str(s)
+                }
+                // If we're under both the maximum and the minimum width, then fill
+                // up the minimum width with the specified string + some alignment.
+                else {
+                    let align = rt::v1::Alignment::Left;
+                    let post_padding = self.padding(width - chars_count, align)?;
+                    self.buf.write_str(s)?;
+                    post_padding.write(self.buf)
+                }
             }
         }
     }
index d8bbd424cf2587d6a16abc08d168fcd585b99377..bd21872e1ad4bcf7fea3e64c30cc556dd7d63996 100644 (file)
@@ -4,7 +4,7 @@
 ///
 /// This `struct` is created by [`Iterator::intersperse`]. See its documentation
 /// for more information.
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 #[derive(Debug, Clone)]
 pub struct Intersperse<I: Iterator>
 where
@@ -24,7 +24,7 @@ pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
     }
 }
 
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 impl<I> Iterator for Intersperse<I>
 where
     I: Iterator,
@@ -61,7 +61,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 ///
 /// This `struct` is created by [`Iterator::intersperse_with`]. See its
 /// documentation for more information.
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 pub struct IntersperseWith<I, G>
 where
     I: Iterator,
@@ -71,7 +71,7 @@ pub struct IntersperseWith<I, G>
     needs_sep: bool,
 }
 
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 impl<I, G> crate::fmt::Debug for IntersperseWith<I, G>
 where
     I: Iterator + crate::fmt::Debug,
@@ -87,7 +87,7 @@ fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
     }
 }
 
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 impl<I, G> crate::clone::Clone for IntersperseWith<I, G>
 where
     I: Iterator + crate::clone::Clone,
@@ -113,7 +113,7 @@ pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
     }
 }
 
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 impl<I, G> Iterator for IntersperseWith<I, G>
 where
     I: Iterator,
index 056ccca1d01c93fb34f97c1c68367ae1f54e7bff..f02d278aff5e4b980375a4000737a426d6f6e0a3 100644 (file)
@@ -42,7 +42,7 @@
 #[stable(feature = "iter_copied", since = "1.36.0")]
 pub use self::copied::Copied;
 
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 pub use self::intersperse::{Intersperse, IntersperseWith};
 
 #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
index 7fb80f954ff407d17d2b5013af0c1bb76017b87c..cd8a26025ffb6291543288cf0a859f034a93dc7a 100644 (file)
     Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
     Skip, SkipWhile, Take, TakeWhile, Zip,
 };
-#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+#[stable(feature = "iter_intersperse", since = "1.56.0")]
 pub use self::adapters::{Intersperse, IntersperseWith};
 
 pub(crate) use self::adapters::process_results;
index 524d8f857e2a5e26db1b757cb25abad31b4626b8..330d3714247c5024d03c8ce9738dac403d282f0f 100644 (file)
@@ -535,8 +535,6 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iter_intersperse)]
-    ///
     /// let mut a = [0, 1, 2].iter().intersperse(&100);
     /// assert_eq!(a.next(), Some(&0));   // The first element from `a`.
     /// assert_eq!(a.next(), Some(&100)); // The separator.
@@ -547,9 +545,8 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
     /// ```
     ///
     /// `intersperse` can be very useful to join an iterator's items using a common element:
-    /// ```
-    /// #![feature(iter_intersperse)]
     ///
+    /// ```
     /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::<String>();
     /// assert_eq!(hello, "Hello World !");
     /// ```
@@ -557,7 +554,7 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
     /// [`Clone`]: crate::clone::Clone
     /// [`intersperse_with`]: Iterator::intersperse_with
     #[inline]
-    #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+    #[stable(feature = "iter_intersperse", since = "1.56.0")]
     fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     where
         Self: Sized,
@@ -582,8 +579,6 @@ fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iter_intersperse)]
-    ///
     /// #[derive(PartialEq, Debug)]
     /// struct NotClone(usize);
     ///
@@ -600,9 +595,8 @@ fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     ///
     /// `intersperse_with` can be used in situations where the separator needs
     /// to be computed:
-    /// ```
-    /// #![feature(iter_intersperse)]
     ///
+    /// ```
     /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied();
     ///
     /// // The closure mutably borrows its context to generate an item.
@@ -615,7 +609,7 @@ fn intersperse(self, separator: Self::Item) -> Intersperse<Self>
     /// [`Clone`]: crate::clone::Clone
     /// [`intersperse`]: Iterator::intersperse
     #[inline]
-    #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+    #[stable(feature = "iter_intersperse", since = "1.56.0")]
     fn intersperse_with<G>(self, separator: G) -> IntersperseWith<Self, G>
     where
         Self: Sized,
@@ -1957,8 +1951,8 @@ fn is_partitioned<P>(mut self, mut predicate: P) -> bool
     /// assert_eq!(it.next(), Some(&40));
     /// ```
     ///
-    /// While you cannot `break` from a closure, the [`crate::ops::ControlFlow`]
-    /// type allows a similar idea:
+    /// While you cannot `break` from a closure, the [`ControlFlow`] type allows
+    /// a similar idea:
     ///
     /// ```
     /// use std::ops::ControlFlow;
@@ -2024,8 +2018,8 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
     /// assert_eq!(it.next(), Some("stale_bread.json"));
     /// ```
     ///
-    /// The [`crate::ops::ControlFlow`] type can be used with this method for the
-    /// situations in which you'd use `break` and `continue` in a normal loop:
+    /// The [`ControlFlow`] type can be used with this method for the situations
+    /// in which you'd use `break` and `continue` in a normal loop:
     ///
     /// ```
     /// use std::ops::ControlFlow;
@@ -2442,14 +2436,14 @@ fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
         R: Try<Output = bool>,
         // FIXME: This bound is rather strange, but means minimal breakage on nightly.
         // See #85115 for the issue tracking a holistic solution for this and try_map.
-        R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+        R: Try<Residual = Result<crate::convert::Infallible, E>>,
     {
         #[inline]
         fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
         where
             F: FnMut(&T) -> R,
             R: Try<Output = bool>,
-            R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+            R: Try<Residual = Result<crate::convert::Infallible, E>>,
         {
             move |(), x| match f(&x).branch() {
                 ControlFlow::Continue(false) => ControlFlow::CONTINUE,
index a4e57fd6a6db46232f1350ca1dbef706026c67dc..d667fff4b81ee8bf4c2c091906515c35e66bd360 100644 (file)
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
+#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 //
 // Library features for const fns:
 #![feature(const_align_of_val)]
 #![feature(const_alloc_layout)]
 #![feature(const_arguments_as_str)]
 #![feature(const_assert_type)]
+#![feature(const_bigint_helper_methods)]
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_discriminant)]
 #![feature(exhaustive_patterns)]
 #![feature(extern_types)]
 #![feature(fundamental)]
+#![feature(if_let_guard)]
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
index c78492f5ae2c9ae0702f5ac06ac3c7de0647456b..2b280773e4c50a2f64abbf7fa8a0386d067b2d7c 100644 (file)
@@ -236,13 +236,8 @@ pub fn dec2flt<F: RawFloat>(s: &str) -> Result<F, ParseFloatError> {
 
     let num = match parse_number(s, negative) {
         Some(r) => r,
-        None => {
-            if let Some(value) = parse_inf_nan(s, negative) {
-                return Ok(value);
-            } else {
-                return Err(pfe_invalid());
-            }
-        }
+        None if let Some(value) = parse_inf_nan(s, negative) => return Ok(value),
+        None => return Err(pfe_invalid()),
     };
     if let Some(value) = num.try_fast_path::<F>() {
         return Ok(value);
index a23ca51ef87d023731b027748cdf74e261d61209..e4599067f85f7328cc54286fec615c8ad5becc30 100644 (file)
@@ -116,8 +116,8 @@ pub const fn i128(val: i128) -> u32 {
 
 macro_rules! impl_checked {
     ($T:ident) => {
-        pub const fn $T(val: $T) -> Option<$T> {
-            if val > 0 { Some(unchecked::$T(val) as $T) } else { None }
+        pub const fn $T(val: $T) -> Option<u32> {
+            if val > 0 { Some(unchecked::$T(val)) } else { None }
         }
     };
 }
index 0bc646995c7c7a13b1d3f91320e25f68e7aa114d..77643290cc455fb16813480c08b029b61846a622 100644 (file)
@@ -918,6 +918,40 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
             }
         }
 
+        /// Saturating integer division. Computes `self / rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(saturating_div)]
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_div(-1), ", stringify!($SelfT), "::MIN + 1);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_div(-1), ", stringify!($SelfT), "::MAX);")]
+        ///
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(saturating_div)]
+        ///
+        #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
+        ///
+        /// ```
+        #[unstable(feature = "saturating_div", issue = "87920")]
+        #[rustc_const_unstable(feature = "saturating_div", issue = "87920")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_div(self, rhs: Self) -> Self {
+            match self.overflowing_div(rhs) {
+                (result, false) => result,
+                (_result, true) => Self::MAX, // MIN / -1 is the only possible saturating overflow
+            }
+        }
+
         /// Saturating integer exponentiation. Computes `self.pow(exp)`,
         /// saturating at the numeric bounds instead of overflowing.
         ///
@@ -1307,6 +1341,33 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self + rhs + carry` without the ability to overflow.
+        ///
+        /// Performs "ternary addition" which takes in an extra bit to add, and may return an
+        /// additional bit of overflow. This allows for chaining together multiple additions
+        /// to create "big integers" which represent larger values.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, false));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
+            let (sum, carry) = (self as $UnsignedT).carrying_add(rhs as $UnsignedT, carry);
+            (sum as $SelfT, carry)
+        }
+
         /// Calculates `self` - `rhs`
         ///
         /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
@@ -1331,6 +1392,33 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self - rhs - borrow` without the ability to overflow.
+        ///
+        /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
+        /// an additional bit of overflow. This allows for chaining together multiple subtractions
+        /// to create "big integers" which represent larger values.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, false));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
+            let (sum, borrow) = (self as $UnsignedT).borrowing_sub(rhs as $UnsignedT, borrow);
+            (sum as $SelfT, borrow)
+        }
+
         /// Calculates the multiplication of `self` and `rhs`.
         ///
         /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow
@@ -1746,6 +1834,173 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
             }
         }
 
+        /// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
+        /// let b = 3;
+        ///
+        /// assert_eq!(a.div_floor(b), 2);
+        /// assert_eq!(a.div_floor(-b), -3);
+        /// assert_eq!((-a).div_floor(b), -3);
+        /// assert_eq!((-a).div_floor(-b), 2);
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_floor(self, rhs: Self) -> Self {
+            let d = self / rhs;
+            let r = self % rhs;
+            if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
+                d - 1
+            } else {
+                d
+            }
+        }
+
+        /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the division results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
+        /// let b = 3;
+        ///
+        /// assert_eq!(a.div_ceil(b), 3);
+        /// assert_eq!(a.div_ceil(-b), -2);
+        /// assert_eq!((-a).div_ceil(b), -2);
+        /// assert_eq!((-a).div_ceil(-b), 3);
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_ceil(self, rhs: Self) -> Self {
+            let d = self / rhs;
+            let r = self % rhs;
+            if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
+                d + 1
+            } else {
+                d
+            }
+        }
+
+        /// If `rhs` is positive, calculates the smallest value greater than or
+        /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
+        /// calculates the largest value less than or equal to `self` that is a
+        /// multiple of `rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the operation results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn next_multiple_of(self, rhs: Self) -> Self {
+            // This would otherwise fail when calculating `r` when self == T::MIN.
+            if rhs == -1 {
+                return self;
+            }
+
+            let r = self % rhs;
+            let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
+                r + rhs
+            } else {
+                r
+            };
+
+            if m == 0 {
+                self
+            } else {
+                self + (rhs - m)
+            }
+        }
+
+        /// If `rhs` is positive, calculates the smallest value greater than or
+        /// equal to `self` that is a multiple of `rhs`. If `rhs` is negative,
+        /// calculates the largest value less than or equal to `self` that is a
+        /// multiple of `rhs`. Returns `None` if `rhs` is zero or the operation
+        /// would result in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(-8), Some(16));")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(8), Some(-16));")]
+        #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-16));")]
+        #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").checked_next_multiple_of(-8), Some(-24));")]
+        #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
+            // This would otherwise fail when calculating `r` when self == T::MIN.
+            if rhs == -1 {
+                return Some(self);
+            }
+
+            let r = try_opt!(self.checked_rem(rhs));
+            let m = if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
+                try_opt!(r.checked_add(rhs))
+            } else {
+                r
+            };
+
+            if m == 0 {
+                Some(self)
+            } else {
+                self.checked_add(try_opt!(rhs.checked_sub(m)))
+            }
+        }
+
         /// Returns the logarithm of the number with respect to an arbitrary base.
         ///
         /// This method might not be optimized owing to implementation details;
@@ -1771,7 +2026,7 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log(self, base: Self) -> Self {
+        pub const fn log(self, base: Self) -> u32 {
             match self.checked_log(base) {
                 Some(n) => n,
                 None => {
@@ -1805,7 +2060,7 @@ pub const fn log(self, base: Self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log2(self) -> Self {
+        pub const fn log2(self) -> u32 {
             match self.checked_log2() {
                 Some(n) => n,
                 None => {
@@ -1839,7 +2094,7 @@ pub const fn log2(self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log10(self) -> Self {
+        pub const fn log10(self) -> u32 {
             match self.checked_log10() {
                 Some(n) => n,
                 None => {
@@ -1870,7 +2125,7 @@ pub const fn log10(self) -> Self {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log(self, base: Self) -> Option<Self> {
+        pub const fn checked_log(self, base: Self) -> Option<u32> {
             if self <= 0 || base <= 1 {
                 None
             } else {
@@ -1906,12 +2161,12 @@ pub const fn checked_log(self, base: Self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log2(self) -> Option<Self> {
+        pub const fn checked_log2(self) -> Option<u32> {
             if self <= 0 {
                 None
             } else {
                 // SAFETY: We just checked that this number is positive
-                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
                 Some(log)
             }
         }
@@ -1930,11 +2185,8 @@ pub const fn checked_log2(self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log10(self) -> Option<Self> {
-            match int_log10::$ActualT(self as $ActualT) {
-                Some(s) => Some(s as Self),
-                None => None,
-            }
+        pub const fn checked_log10(self) -> Option<u32> {
+            int_log10::$ActualT(self as $ActualT)
         }
 
         /// Computes the absolute value of `self`.
index 9788404dd05bf58f6c18ba5ac18e8d2735595595..59b68cbe9c0ceb318af73074de99c0959aae936d 100644 (file)
@@ -43,8 +43,12 @@ macro_rules! unlikely {
 mod error;
 mod int_log10;
 mod nonzero;
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+mod saturating;
 mod wrapping;
 
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+pub use saturating::Saturating;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use wrapping::Wrapping;
 
@@ -89,20 +93,96 @@ macro_rules! usize_isize_from_xe_bytes_doc {
     };
 }
 
+macro_rules! widening_impl {
+    ($SelfT:ty, $WideT:ty, $BITS:literal) => {
+        /// Calculates the complete product `self * rhs` without the possibility to overflow.
+        ///
+        /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
+        /// of the result as two separate values, in that order.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// Please note that this example is shared between integer types.
+        /// Which explains why `u32` is used here.
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// assert_eq!(5u32.widening_mul(2), (10, 0));
+        /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
+            // note: longer-term this should be done via an intrinsic,
+            //   but for now we can deal without an impl for u128/i128
+            // SAFETY: overflow will be contained within the wider types
+            let wide = unsafe { (self as $WideT).unchecked_mul(rhs as $WideT) };
+            (wide as $SelfT, (wide >> $BITS) as $SelfT)
+        }
+
+        /// Calculates the "full multiplication" `self * rhs + carry`
+        /// without the possibility to overflow.
+        ///
+        /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
+        /// of the result as two separate values, in that order.
+        ///
+        /// Performs "long multiplication" which takes in an extra amount to add, and may return an
+        /// additional amount of overflow. This allows for chaining together multiple
+        /// multiplications to create "big integers" which represent larger values.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// Please note that this example is shared between integer types.
+        /// Which explains why `u32` is used here.
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
+        /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
+        /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
+        /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
+            // note: longer-term this should be done via an intrinsic,
+            //   but for now we can deal without an impl for u128/i128
+            // SAFETY: overflow will be contained within the wider types
+            let wide = unsafe {
+                (self as $WideT).unchecked_mul(rhs as $WideT).unchecked_add(carry as $WideT)
+            };
+            (wide as $SelfT, (wide >> $BITS) as $SelfT)
+        }
+    };
+}
+
 #[lang = "i8"]
 impl i8 {
+    widening_impl! { i8, i16, 8 }
     int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
     "[0x12]", "[0x12]", "", "" }
 }
 
 #[lang = "i16"]
 impl i16 {
+    widening_impl! { i16, i32, 16 }
     int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
     "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "i32"]
 impl i32 {
+    widening_impl! { i32, i64, 32 }
     int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]", "", "" }
@@ -110,6 +190,7 @@ impl i32 {
 
 #[lang = "i64"]
 impl i64 {
+    widening_impl! { i64, i128, 64 }
     int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
     "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
     "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@@ -131,6 +212,7 @@ impl i128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
+    widening_impl! { isize, i32, 16 }
     int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
     "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@@ -139,6 +221,7 @@ impl isize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "isize"]
 impl isize {
+    widening_impl! { isize, i64, 32 }
     int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
     "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
     "[0x12, 0x34, 0x56, 0x78]",
@@ -148,6 +231,7 @@ impl isize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "isize"]
 impl isize {
+    widening_impl! { isize, i128, 64 }
     int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
     12, "0xaa00000000006e1", "0x6e10aa",  "0x1234567890123456", "0x5634129078563412",
      "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@@ -160,6 +244,7 @@ impl isize {
 
 #[lang = "u8"]
 impl u8 {
+    widening_impl! { u8, u16, 8 }
     uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
     "[0x12]", "", "" }
 
@@ -693,18 +778,21 @@ pub fn escape_ascii(&self) -> ascii::EscapeDefault {
 
 #[lang = "u16"]
 impl u16 {
+    widening_impl! { u16, u32, 16 }
     uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
 }
 
 #[lang = "u32"]
 impl u32 {
+    widening_impl! { u32, u64, 32 }
     uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
 }
 
 #[lang = "u64"]
 impl u64 {
+    widening_impl! { u64, u128, 64 }
     uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@@ -727,6 +815,7 @@ impl u128 {
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
+    widening_impl! { usize, u32, 16 }
     uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
     "[0x34, 0x12]", "[0x12, 0x34]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@@ -734,6 +823,7 @@ impl usize {
 #[cfg(target_pointer_width = "32")]
 #[lang = "usize"]
 impl usize {
+    widening_impl! { usize, u64, 32 }
     uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
     "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
     usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@@ -742,6 +832,7 @@ impl usize {
 #[cfg(target_pointer_width = "64")]
 #[lang = "usize"]
 impl usize {
+    widening_impl! { usize, u128, 64 }
     uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
     "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
     "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs
new file mode 100644 (file)
index 0000000..f6dd360
--- /dev/null
@@ -0,0 +1,976 @@
+//! Definitions of `Saturating<T>`.
+
+use crate::fmt;
+use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign};
+use crate::ops::{BitXor, BitXorAssign, Div, DivAssign};
+use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign};
+use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
+
+/// Provides intentionally-saturating arithmetic on `T`.
+///
+/// Operations like `+` on `u32` values are intended to never overflow,
+/// and in some debug configurations overflow is detected and results
+/// in a panic. While most arithmetic falls into this category, some
+/// code explicitly expects and relies upon saturating arithmetic.
+///
+/// Saturating arithmetic can be achieved either through methods like
+/// `saturating_add`, or through the `Saturating<T>` type, which says that
+/// all standard arithmetic operations on the underlying value are
+/// intended to have saturating semantics.
+///
+/// The underlying value can be retrieved through the `.0` index of the
+/// `Saturating` tuple.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(saturating_int_impl)]
+/// use std::num::Saturating;
+///
+/// let max = Saturating(u32::MAX);
+/// let one = Saturating(1u32);
+///
+/// assert_eq!(u32::MAX, (max + one).0);
+/// ```
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
+#[repr(transparent)]
+pub struct Saturating<T>(#[unstable(feature = "saturating_int_impl", issue = "87920")] pub T);
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::Debug> fmt::Debug for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::Display> fmt::Display for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::Binary> fmt::Binary for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::Octal> fmt::Octal for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::LowerHex> fmt::LowerHex for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+impl<T: fmt::UpperHex> fmt::UpperHex for Saturating<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+#[allow(unused_macros)]
+macro_rules! sh_impl_signed {
+    ($t:ident, $f:ident) => {
+        // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
+        //
+        // #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        // impl Shl<$f> for Saturating<$t> {
+        //     type Output = Saturating<$t>;
+        //
+        //     #[inline]
+        //     fn shl(self, other: $f) -> Saturating<$t> {
+        //         if other < 0 {
+        //             Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
+        //         } else {
+        //             Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
+        //         }
+        //     }
+        // }
+        // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
+        // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+        //
+        // #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        // impl ShlAssign<$f> for Saturating<$t> {
+        //     #[inline]
+        //     fn shl_assign(&mut self, other: $f) {
+        //         *self = *self << other;
+        //     }
+        // }
+        // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Shr<$f> for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn shr(self, other: $f) -> Saturating<$t> {
+                if other < 0 {
+                    Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
+                } else {
+                    Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
+                }
+            }
+        }
+        forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
+        #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl ShrAssign<$f> for Saturating<$t> {
+            #[inline]
+            fn shr_assign(&mut self, other: $f) {
+                *self = *self >> other;
+            }
+        }
+        forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
+    };
+}
+
+macro_rules! sh_impl_unsigned {
+    ($t:ident, $f:ident) => {
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Shl<$f> for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn shl(self, other: $f) -> Saturating<$t> {
+                Saturating(self.0.wrapping_shl(other as u32))
+            }
+        }
+        forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
+        #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl ShlAssign<$f> for Saturating<$t> {
+            #[inline]
+            fn shl_assign(&mut self, other: $f) {
+                *self = *self << other;
+            }
+        }
+        forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Shr<$f> for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn shr(self, other: $f) -> Saturating<$t> {
+                Saturating(self.0.wrapping_shr(other as u32))
+            }
+        }
+        forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
+        #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl ShrAssign<$f> for Saturating<$t> {
+            #[inline]
+            fn shr_assign(&mut self, other: $f) {
+                *self = *self >> other;
+            }
+        }
+        forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
+    };
+}
+
+// FIXME (#23545): uncomment the remaining impls
+macro_rules! sh_impl_all {
+    ($($t:ident)*) => ($(
+        //sh_impl_unsigned! { $t, u8 }
+        //sh_impl_unsigned! { $t, u16 }
+        //sh_impl_unsigned! { $t, u32 }
+        //sh_impl_unsigned! { $t, u64 }
+        //sh_impl_unsigned! { $t, u128 }
+        sh_impl_unsigned! { $t, usize }
+
+        //sh_impl_signed! { $t, i8 }
+        //sh_impl_signed! { $t, i16 }
+        //sh_impl_signed! { $t, i32 }
+        //sh_impl_signed! { $t, i64 }
+        //sh_impl_signed! { $t, i128 }
+        //sh_impl_signed! { $t, isize }
+    )*)
+}
+
+sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
+
+// FIXME(30524): impl Op<T> for Saturating<T>, impl OpAssign<T> for Saturating<T>
+macro_rules! saturating_impl {
+    ($($t:ty)*) => ($(
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Add for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn add(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0.saturating_add(other.0))
+            }
+        }
+        forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl AddAssign for Saturating<$t> {
+            #[inline]
+            fn add_assign(&mut self, other: Saturating<$t>) {
+                *self = *self + other;
+            }
+        }
+        forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Sub for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn sub(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0.saturating_sub(other.0))
+            }
+        }
+        forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl SubAssign for Saturating<$t> {
+            #[inline]
+            fn sub_assign(&mut self, other: Saturating<$t>) {
+                *self = *self - other;
+            }
+        }
+        forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Mul for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn mul(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0.saturating_mul(other.0))
+            }
+        }
+        forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl MulAssign for Saturating<$t> {
+            #[inline]
+            fn mul_assign(&mut self, other: Saturating<$t>) {
+                *self = *self * other;
+            }
+        }
+        forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> }
+
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(saturating_int_impl, saturating_div)]
+        /// use std::num::Saturating;
+        ///
+        #[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")]
+        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MAX), Saturating(", stringify!($t), "::MAX) / Saturating(1));")]
+        #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN), Saturating(", stringify!($t), "::MIN) / Saturating(1));")]
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(saturating_int_impl, saturating_div)]
+        /// use std::num::Saturating;
+        ///
+        #[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")]
+        /// ```
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Div for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn div(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0.saturating_div(other.0))
+            }
+        }
+        forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl DivAssign for Saturating<$t> {
+            #[inline]
+            fn div_assign(&mut self, other: Saturating<$t>) {
+                *self = *self / other;
+            }
+        }
+        forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Rem for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn rem(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0.rem(other.0))
+            }
+        }
+        forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl RemAssign for Saturating<$t> {
+            #[inline]
+            fn rem_assign(&mut self, other: Saturating<$t>) {
+                *self = *self % other;
+            }
+        }
+        forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Not for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn not(self) -> Saturating<$t> {
+                Saturating(!self.0)
+            }
+        }
+        forward_ref_unop! { impl Not, not for Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitXor for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn bitxor(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0 ^ other.0)
+            }
+        }
+        forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitXorAssign for Saturating<$t> {
+            #[inline]
+            fn bitxor_assign(&mut self, other: Saturating<$t>) {
+                *self = *self ^ other;
+            }
+        }
+        forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitOr for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn bitor(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0 | other.0)
+            }
+        }
+        forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitOrAssign for Saturating<$t> {
+            #[inline]
+            fn bitor_assign(&mut self, other: Saturating<$t>) {
+                *self = *self | other;
+            }
+        }
+        forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitAnd for Saturating<$t> {
+            type Output = Saturating<$t>;
+
+            #[inline]
+            fn bitand(self, other: Saturating<$t>) -> Saturating<$t> {
+                Saturating(self.0 & other.0)
+            }
+        }
+        forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl BitAndAssign for Saturating<$t> {
+            #[inline]
+            fn bitand_assign(&mut self, other: Saturating<$t>) {
+                *self = *self & other;
+            }
+        }
+        forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> }
+
+    )*)
+}
+
+saturating_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+macro_rules! saturating_int_impl {
+    ($($t:ty)*) => ($(
+        impl Saturating<$t> {
+            /// Returns the smallest value that can be represented by this integer type.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MIN, Saturating(", stringify!($t), "::MIN));")]
+            /// ```
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const MIN: Self = Self(<$t>::MIN);
+
+            /// Returns the largest value that can be represented by this integer type.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MAX, Saturating(", stringify!($t), "::MAX));")]
+            /// ```
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const MAX: Self = Self(<$t>::MAX);
+
+            /// Returns the size of this integer type in bits.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::BITS, ", stringify!($t), "::BITS);")]
+            /// ```
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const BITS: u32 = <$t>::BITS;
+
+            /// Returns the number of ones in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")]
+            ///
+            /// assert_eq!(n.count_ones(), 3);
+            /// ```
+            #[inline]
+            #[doc(alias = "popcount")]
+            #[doc(alias = "popcnt")]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn count_ones(self) -> u32 {
+                self.0.count_ones()
+            }
+
+            /// Returns the number of zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn count_zeros(self) -> u32 {
+                self.0.count_zeros()
+            }
+
+            /// Returns the number of trailing zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")]
+            ///
+            /// assert_eq!(n.trailing_zeros(), 3);
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn trailing_zeros(self) -> u32 {
+                self.0.trailing_zeros()
+            }
+
+            /// Shifts the bits to the left by a specified amount, `n`,
+            /// saturating the truncated bits to the end of the resulting
+            /// integer.
+            ///
+            /// Please note this isn't the same operation as the `<<` shifting
+            /// operator!
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
+            /// let m: Saturating<i64> = Saturating(-0x76543210FEDCBA99);
+            ///
+            /// assert_eq!(n.rotate_left(32), m);
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn rotate_left(self, n: u32) -> Self {
+                Saturating(self.0.rotate_left(n))
+            }
+
+            /// Shifts the bits to the right by a specified amount, `n`,
+            /// saturating the truncated bits to the beginning of the resulting
+            /// integer.
+            ///
+            /// Please note this isn't the same operation as the `>>` shifting
+            /// operator!
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            /// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
+            /// let m: Saturating<i64> = Saturating(-0xFEDCBA987654322);
+            ///
+            /// assert_eq!(n.rotate_right(4), m);
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn rotate_right(self, n: u32) -> Self {
+                Saturating(self.0.rotate_right(n))
+            }
+
+            /// Reverses the byte order of the integer.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            /// let n: Saturating<i16> = Saturating(0b0000000_01010101);
+            /// assert_eq!(n, Saturating(85));
+            ///
+            /// let m = n.swap_bytes();
+            ///
+            /// assert_eq!(m, Saturating(0b01010101_00000000));
+            /// assert_eq!(m, Saturating(21760));
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn swap_bytes(self) -> Self {
+                Saturating(self.0.swap_bytes())
+            }
+
+            /// Reverses the bit pattern of the integer.
+            ///
+            /// # Examples
+            ///
+            /// Please note that this example is shared between integer types.
+            /// Which explains why `i16` is used here.
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            /// let n = Saturating(0b0000000_01010101i16);
+            /// assert_eq!(n, Saturating(85));
+            ///
+            /// let m = n.reverse_bits();
+            ///
+            /// assert_eq!(m.0 as u16, 0b10101010_00000000);
+            /// assert_eq!(m, Saturating(-22016));
+            /// ```
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")]
+            #[inline]
+            #[must_use]
+            pub const fn reverse_bits(self) -> Self {
+                Saturating(self.0.reverse_bits())
+            }
+
+            /// Converts an integer from big endian to the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "big") {
+            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_be(n), n)")]
+            /// } else {
+            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_be(n), n.swap_bytes())")]
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn from_be(x: Self) -> Self {
+                Saturating(<$t>::from_be(x.0))
+            }
+
+            /// Converts an integer from little endian to the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "little") {
+            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_le(n), n)")]
+            /// } else {
+            #[doc = concat!("    assert_eq!(<Saturating<", stringify!($t), ">>::from_le(n), n.swap_bytes())")]
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn from_le(x: Self) -> Self {
+                Saturating(<$t>::from_le(x.0))
+            }
+
+            /// Converts `self` to big endian from the target's endianness.
+            ///
+            /// On big endian this is a no-op. On little endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "big") {
+            ///     assert_eq!(n.to_be(), n)
+            /// } else {
+            ///     assert_eq!(n.to_be(), n.swap_bytes())
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn to_be(self) -> Self {
+                Saturating(self.0.to_be())
+            }
+
+            /// Converts `self` to little endian from the target's endianness.
+            ///
+            /// On little endian this is a no-op. On big endian the bytes are
+            /// swapped.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
+            ///
+            /// if cfg!(target_endian = "little") {
+            ///     assert_eq!(n.to_le(), n)
+            /// } else {
+            ///     assert_eq!(n.to_le(), n.swap_bytes())
+            /// }
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn to_le(self) -> Self {
+                Saturating(self.0.to_le())
+            }
+
+            /// Raises self to the power of `exp`, using exponentiation by squaring.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")]
+            /// ```
+            ///
+            /// Results that are too large are saturated:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            /// assert_eq!(Saturating(3i8).pow(5), Saturating(127));
+            /// assert_eq!(Saturating(3i8).pow(6), Saturating(127));
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub fn pow(self, exp: u32) -> Self {
+                Saturating(self.0.saturating_pow(exp))
+            }
+        }
+    )*)
+}
+
+saturating_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
+
+macro_rules! saturating_int_impl_signed {
+    ($($t:ty)*) => ($(
+        impl Saturating<$t> {
+            /// Returns the number of leading zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
+            ///
+            /// assert_eq!(n.leading_zeros(), 3);
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn leading_zeros(self) -> u32 {
+                self.0.leading_zeros()
+            }
+
+            /// Saturating absolute value. Computes `self.abs()`, returning `MAX` if `self == MIN`
+            /// instead of overflowing.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")]
+            #[doc = concat!("assert_eq!(Saturating(-100", stringify!($t), ").abs(), Saturating(100));")]
+            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating((", stringify!($t), "::MIN + 1).abs()));")]
+            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MIN.saturating_abs()));")]
+            #[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub fn abs(self) -> Saturating<$t> {
+                Saturating(self.0.saturating_abs())
+            }
+
+            /// Returns a number representing sign of `self`.
+            ///
+            ///  - `0` if the number is zero
+            ///  - `1` if the number is positive
+            ///  - `-1` if the number is negative
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")]
+            #[doc = concat!("assert_eq!(Saturating(0", stringify!($t), ").signum(), Saturating(0));")]
+            #[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub fn signum(self) -> Saturating<$t> {
+                Saturating(self.0.signum())
+            }
+
+            /// Returns `true` if `self` is positive and `false` if the number is zero or
+            /// negative.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")]
+            #[doc = concat!("assert!(!Saturating(-10", stringify!($t), ").is_positive());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn is_positive(self) -> bool {
+                self.0.is_positive()
+            }
+
+            /// Returns `true` if `self` is negative and `false` if the number is zero or
+            /// positive.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")]
+            #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_negative());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn is_negative(self) -> bool {
+                self.0.is_negative()
+            }
+        }
+
+        #[unstable(feature = "saturating_int_impl", issue = "87920")]
+        impl Neg for Saturating<$t> {
+            type Output = Self;
+            #[inline]
+            fn neg(self) -> Self {
+                Saturating(self.0.saturating_neg())
+            }
+        }
+        forward_ref_unop! { impl Neg, neg for Saturating<$t>,
+                #[unstable(feature = "saturating_int_impl", issue = "87920")] }
+    )*)
+}
+
+saturating_int_impl_signed! { isize i8 i16 i32 i64 i128 }
+
+macro_rules! saturating_int_impl_unsigned {
+    ($($t:ty)*) => ($(
+        impl Saturating<$t> {
+            /// Returns the number of leading zeros in the binary representation of `self`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
+            ///
+            /// assert_eq!(n.leading_zeros(), 2);
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub const fn leading_zeros(self) -> u32 {
+                self.0.leading_zeros()
+            }
+
+            /// Returns `true` if and only if `self == 2^k` for some `k`.
+            ///
+            /// # Examples
+            ///
+            /// Basic usage:
+            ///
+            /// ```
+            /// #![feature(saturating_int_impl)]
+            /// use std::num::Saturating;
+            ///
+            #[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")]
+            #[doc = concat!("assert!(!Saturating(10", stringify!($t), ").is_power_of_two());")]
+            /// ```
+            #[inline]
+            #[unstable(feature = "saturating_int_impl", issue = "87920")]
+            pub fn is_power_of_two(self) -> bool {
+                self.0.is_power_of_two()
+            }
+
+        }
+    )*)
+}
+
+saturating_int_impl_unsigned! { usize u8 u16 u32 u64 u128 }
+
+// Related to potential Shl and ShlAssign implementation
+//
+// mod shift_max {
+//     #![allow(non_upper_case_globals)]
+//
+//     #[cfg(target_pointer_width = "16")]
+//     mod platform {
+//         pub const usize: u32 = super::u16;
+//         pub const isize: u32 = super::i16;
+//     }
+//
+//     #[cfg(target_pointer_width = "32")]
+//     mod platform {
+//         pub const usize: u32 = super::u32;
+//         pub const isize: u32 = super::i32;
+//     }
+//
+//     #[cfg(target_pointer_width = "64")]
+//     mod platform {
+//         pub const usize: u32 = super::u64;
+//         pub const isize: u32 = super::i64;
+//     }
+//
+//     pub const i8: u32 = (1 << 3) - 1;
+//     pub const i16: u32 = (1 << 4) - 1;
+//     pub const i32: u32 = (1 << 5) - 1;
+//     pub const i64: u32 = (1 << 6) - 1;
+//     pub const i128: u32 = (1 << 7) - 1;
+//     pub use self::platform::isize;
+//
+//     pub const u8: u32 = i8;
+//     pub const u16: u32 = i16;
+//     pub const u32: u32 = i32;
+//     pub const u64: u32 = i64;
+//     pub const u128: u32 = i128;
+//     pub use self::platform::usize;
+// }
index ae113a47e95d61a0b7712471012694045fb6207f..46e64c33b84d77cb7f207abc3f132db3b7fa2cd5 100644 (file)
@@ -660,7 +660,7 @@ pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log(self, base: Self) -> Self {
+        pub const fn log(self, base: Self) -> u32 {
             match self.checked_log(base) {
                 Some(n) => n,
                 None => {
@@ -694,7 +694,7 @@ pub const fn log(self, base: Self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log2(self) -> Self {
+        pub const fn log2(self) -> u32 {
             match self.checked_log2() {
                 Some(n) => n,
                 None => {
@@ -728,7 +728,7 @@ pub const fn log2(self) -> Self {
         #[track_caller]
         #[rustc_inherit_overflow_checks]
         #[allow(arithmetic_overflow)]
-        pub const fn log10(self) -> Self {
+        pub const fn log10(self) -> u32 {
             match self.checked_log10() {
                 Some(n) => n,
                 None => {
@@ -759,7 +759,7 @@ pub const fn log10(self) -> Self {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log(self, base: Self) -> Option<Self> {
+        pub const fn checked_log(self, base: Self) -> Option<u32> {
             if self <= 0 || base <= 1 {
                 None
             } else {
@@ -795,12 +795,12 @@ pub const fn checked_log(self, base: Self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log2(self) -> Option<Self> {
+        pub const fn checked_log2(self) -> Option<u32> {
             if self <= 0 {
                 None
             } else {
                 // SAFETY: We just checked that this number is positive
-                let log = (Self::BITS - 1) as Self - unsafe { intrinsics::ctlz_nonzero(self) };
+                let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 };
                 Some(log)
             }
         }
@@ -819,11 +819,8 @@ pub const fn checked_log2(self) -> Option<Self> {
         #[must_use = "this returns the result of the operation, \
                         without modifying the original"]
         #[inline]
-        pub const fn checked_log10(self) -> Option<Self> {
-            match int_log10::$ActualT(self as $ActualT) {
-                Some(s) => Some(s as Self),
-                None => None,
-            }
+        pub const fn checked_log10(self) -> Option<u32> {
+            int_log10::$ActualT(self as $ActualT)
         }
 
         /// Checked negation. Computes `-self`, returning `None` unless `self ==
@@ -1041,6 +1038,36 @@ pub const fn saturating_mul(self, rhs: Self) -> Self {
             }
         }
 
+        /// Saturating integer division. Computes `self / rhs`, saturating at the
+        /// numeric bounds instead of overflowing.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(saturating_div)]
+        ///
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")]
+        ///
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(saturating_div)]
+        ///
+        #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
+        ///
+        /// ```
+        #[unstable(feature = "saturating_div", issue = "87920")]
+        #[rustc_const_unstable(feature = "saturating_div", issue = "87920")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn saturating_div(self, rhs: Self) -> Self {
+            // on unsigned types, there is no overflow in integer division
+            self.wrapping_div(rhs)
+        }
+
         /// Saturating integer exponentiation. Computes `self.pow(exp)`,
         /// saturating at the numeric bounds instead of overflowing.
         ///
@@ -1378,6 +1405,36 @@ pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self + rhs + carry` without the ability to overflow.
+        ///
+        /// Performs "ternary addition" which takes in an extra bit to add, and may return an
+        /// additional bit of overflow. This allows for chaining together multiple additions
+        /// to create "big integers" which represent larger values.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
+            // note: longer-term this should be done via an intrinsic, but this has been shown
+            //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
+            let (a, b) = self.overflowing_add(rhs);
+            let (c, d) = a.overflowing_add(carry as $SelfT);
+            (c, b | d)
+        }
+
         /// Calculates `self` - `rhs`
         ///
         /// Returns a tuple of the subtraction along with a boolean indicating
@@ -1403,6 +1460,36 @@ pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
             (a as Self, b)
         }
 
+        /// Calculates `self - rhs - borrow` without the ability to overflow.
+        ///
+        /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
+        /// an additional bit of overflow. This allows for chaining together multiple subtractions
+        /// to create "big integers" which represent larger values.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage
+        ///
+        /// ```
+        /// #![feature(bigint_helper_methods)]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
+        #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, true));")]
+        #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
+        /// ```
+        #[unstable(feature = "bigint_helper_methods", issue = "85532")]
+        #[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
+            // note: longer-term this should be done via an intrinsic, but this has been shown
+            //   to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
+            let (a, b) = self.overflowing_sub(rhs);
+            let (c, d) = a.overflowing_sub(borrow as $SelfT);
+            (c, b | d)
+        }
+
         /// Calculates the multiplication of `self` and `rhs`.
         ///
         /// Returns a tuple of the multiplication along with a boolean
@@ -1758,6 +1845,110 @@ pub const fn rem_euclid(self, rhs: Self) -> Self {
             self % rhs
         }
 
+        /// Calculates the quotient of `self` and `rhs`, rounding the result towards negative infinity.
+        ///
+        /// This is the same as performing `self / rhs` for all unsigned integers.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[inline(always)]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_floor(self, rhs: Self) -> Self {
+            self / rhs
+        }
+
+        /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn div_ceil(self, rhs: Self) -> Self {
+            let d = self / rhs;
+            let r = self % rhs;
+            if r > 0 && rhs > 0 {
+                d + 1
+            } else {
+                d
+            }
+        }
+
+        /// Calculates the smallest value greater than or equal to `self` that
+        /// is a multiple of `rhs`.
+        ///
+        /// # Panics
+        ///
+        /// This function will panic if `rhs` is 0 or the operation results in overflow.
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn next_multiple_of(self, rhs: Self) -> Self {
+            match self % rhs {
+                0 => self,
+                r => self + (rhs - r)
+            }
+        }
+
+        /// Calculates the smallest value greater than or equal to `self` that
+        /// is a multiple of `rhs`. If `rhs` is negative,
+        ///
+        /// # Examples
+        ///
+        /// Basic usage:
+        ///
+        /// ```
+        /// #![feature(int_roundings)]
+        #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(16));")]
+        #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".checked_next_multiple_of(8), Some(24));")]
+        #[doc = concat!("assert_eq!(1_", stringify!($SelfT), ".checked_next_multiple_of(0), None);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.checked_next_multiple_of(2), None);")]
+        /// ```
+        #[unstable(feature = "int_roundings", issue = "88581")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        pub const fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
+            match try_opt!(self.checked_rem(rhs)) {
+                0 => Some(self),
+                r => self.checked_add(try_opt!(rhs.checked_sub(r)))
+            }
+        }
+
         /// Returns `true` if and only if `self == 2^k` for some `k`.
         ///
         /// # Examples
index c2270c864dfae26b5fe20333a66e8eee22238cf5..cd2d57699c92c95e797b647c68480d0c60905377 100644 (file)
@@ -63,7 +63,7 @@ pub enum ControlFlow<B, C = ()> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::TryV2 for ControlFlow<B, C> {
+impl<B, C> ops::Try for ControlFlow<B, C> {
     type Output = C;
     type Residual = ControlFlow<B, convert::Infallible>;
 
@@ -165,7 +165,7 @@ pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
 /// These are used only as part of implementing the iterator adapters.
 /// They have mediocre names and non-obvious semantics, so aren't
 /// currently on a path to potential stabilization.
-impl<R: ops::TryV2> ControlFlow<R, R::Output> {
+impl<R: ops::Try> ControlFlow<R, R::Output> {
     /// Create a `ControlFlow` from any type implementing `Try`.
     #[inline]
     pub(crate) fn from_try(r: R) -> Self {
index 85e04740d96a4836001e6e427de2d3213ed9db9d..bd7feb8b183ced5c29727a33299ae357ec72fa47 100644 (file)
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-pub use self::try_trait::FromResidual;
-
-#[unstable(feature = "try_trait_v2", issue = "84277")]
-pub use self::try_trait::Try;
-
-#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
-pub(crate) use self::try_trait::Try as TryV2;
+pub use self::try_trait::{FromResidual, Try};
 
 #[unstable(feature = "generator_trait", issue = "43122")]
 pub use self::generator::{Generator, GeneratorState};
index 78f5954532ff08e5161e7cd422106a93a9f1ffd5..9d5e03dd0de795eeefe17466421e81b0b203ee72 100644 (file)
@@ -1198,11 +1198,8 @@ pub fn xor(self, optb: Option<T>) -> Option<T> {
     pub fn insert(&mut self, value: T) -> &mut T {
         *self = Some(value);
 
-        match self {
-            Some(v) => v,
-            // SAFETY: the code above just filled the option
-            None => unsafe { hint::unreachable_unchecked() },
-        }
+        // SAFETY: the code above just filled the option
+        unsafe { self.as_mut().unwrap_unchecked() }
     }
 
     /// Inserts `value` into the option if it is [`None`], then
@@ -2013,7 +2010,7 @@ fn from_iter<I: IntoIterator<Item = Option<A>>>(iter: I) -> Option<V> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T> ops::TryV2 for Option<T> {
+impl<T> ops::Try for Option<T> {
     type Output = T;
     type Residual = Option<convert::Infallible>;
 
index 02c9dadc0868dcb5067124963c8d3d8f5f760d31..014170604ecaa573230c0de95f0d19709a694186 100644 (file)
 /// // Ensure that the last item was dropped.
 /// assert!(weak.upgrade().is_none());
 /// ```
-///
-/// Notice that the compiler performs this copy automatically when dropping packed structs,
-/// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
-/// manually.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
index 861790e8a4099cd03c2f325c6745373c1f2e9628..092e6544342b7f4e2105ce21fd9b81d25d29bede 100644 (file)
@@ -1889,7 +1889,7 @@ fn from_iter<I: IntoIterator<Item = Result<A, E>>>(iter: I) -> Result<V, E> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Result<T, E> {
+impl<T, E> ops::Try for Result<T, E> {
     type Output = T;
     type Residual = Result<convert::Infallible, E>;
 
index 36c2c4abdb4c5b0611e0b489e703bd1a71c3d785..8a31388fbdbbc6b68704022a2de0f4e09d50f5b6 100644 (file)
@@ -369,6 +369,22 @@ macro_rules! right {
             // Instead of swapping one pair at the time, it is more efficient to perform a cyclic
             // permutation. This is not strictly equivalent to swapping, but produces a similar
             // result using fewer memory operations.
+
+            // SAFETY: The use of `ptr::read` is valid because there is at least one element in
+            // both `offsets_l` and `offsets_r`, so `left!` is a valid pointer to read from.
+            //
+            // The uses of `left!` involve calls to `offset` on `l`, which points to the
+            // beginning of `v`. All the offsets pointed-to by `start_l` are at most `block_l`, so
+            // these `offset` calls are safe as all reads are within the block. The same argument
+            // applies for the uses of `right!`.
+            //
+            // The calls to `start_l.offset` are valid because there are at most `count-1` of them,
+            // plus the final one at the end of the unsafe block, where `count` is the minimum number
+            // of collected offsets in `offsets_l` and `offsets_r`, so there is no risk of there not
+            // being enough elements. The same reasoning applies to the calls to `start_r.offset`.
+            //
+            // The calls to `copy_nonoverlapping` are safe because `left!` and `right!` are guaranteed
+            // not to overlap, and are valid because of the reasoning above.
             unsafe {
                 let tmp = ptr::read(left!());
                 ptr::copy_nonoverlapping(right!(), left!(), 1);
@@ -389,11 +405,21 @@ macro_rules! right {
 
         if start_l == end_l {
             // All out-of-order elements in the left block were moved. Move to the next block.
+
+            // block-width-guarantee
+            // SAFETY: if `!is_done` then the slice width is guaranteed to be at least `2*BLOCK` wide. There
+            // are at most `BLOCK` elements in `offsets_l` because of its size, so the `offset` operation is
+            // safe. Otherwise, the debug assertions in the `is_done` case guarantee that
+            // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
+            // for the smaller number of remaining elements.
             l = unsafe { l.offset(block_l as isize) };
         }
 
         if start_r == end_r {
             // All out-of-order elements in the right block were moved. Move to the previous block.
+
+            // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
+            // or `block_r` has been adjusted for the last handful of elements.
             r = unsafe { r.offset(-(block_r as isize)) };
         }
 
index 947afbdc68dfbcbfced52b632f15b42cf774f19c..ca4e2e6b7f3517af02727acb916d047e8bf4f2d5 100644 (file)
@@ -69,7 +69,7 @@
 pub use iter::SplitInclusive;
 
 #[unstable(feature = "str_internals", issue = "none")]
-pub use validations::next_code_point;
+pub use validations::{next_code_point, utf8_char_width};
 
 use iter::MatchIndicesInternal;
 use iter::SplitInternal;
index fc0a4e747973a15c48299b5b5b8d7548d8d61edb..250704609963217e62828be3ae43c2a1f7eaca10 100644 (file)
@@ -222,7 +222,7 @@ fn from(t: T) -> Poll<T> {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Poll<Result<T, E>> {
+impl<T, E> ops::Try for Poll<Result<T, E>> {
     type Output = Poll<T>;
     type Residual = Result<convert::Infallible, E>;
 
@@ -252,7 +252,7 @@ fn from_residual(x: Result<convert::Infallible, E>) -> Self {
 }
 
 #[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<T, E> ops::TryV2 for Poll<Option<Result<T, E>>> {
+impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
     type Output = Poll<Option<T>>;
     type Residual = Result<convert::Infallible, E>;
 
index 2d8a1cb1ab01639757cc0efc20ed062da46cdb7c..35b740cd74372b9a03a1343bf9445c01d7cb9a5a 100644 (file)
@@ -2,14 +2,21 @@
 
 //! Temporal quantification.
 //!
-//! Example:
+//! # Examples:
+//!
+//! There are multiple ways to create a new [`Duration`]:
 //!
 //! ```
-//! use std::time::Duration;
+//! # use std::time::Duration;
+//! let five_seconds = Duration::from_secs(5);
+//! assert_eq!(five_seconds, Duration::from_millis(5_000));
+//! assert_eq!(five_seconds, Duration::from_micros(5_000_000));
+//! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
 //!
-//! let five_seconds = Duration::new(5, 0);
-//! // both declarations are equivalent
-//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
+//! let ten_seconds = Duration::from_secs(10);
+//! let seven_nanos = Duration::from_nanos(7);
+//! let total = ten_seconds + seven_nanos;
+//! assert_eq!(total, Duration::new(10, 7));
 //! ```
 
 use crate::fmt;
index 77517879dd2507f20df999d24caf294e5599042d..85a006c5d5bef7ebca5a4146ae651a1f5891b298 100644 (file)
@@ -2,6 +2,38 @@
 use core::default::Default;
 use std::mem::drop;
 
+#[test]
+fn smoketest_unsafe_cell() {
+    let mut x = UnsafeCell::new(10);
+    let ref_mut = &mut x;
+    unsafe {
+        // The asserts are repeated in order to ensure that `get()`
+        // is non-mutating.
+        assert_eq!(*ref_mut.get(), 10);
+        assert_eq!(*ref_mut.get(), 10);
+        *ref_mut.get_mut() += 5;
+        assert_eq!(*ref_mut.get(), 15);
+        assert_eq!(*ref_mut.get(), 15);
+        assert_eq!(x.into_inner(), 15);
+    }
+}
+
+#[test]
+fn unsafe_cell_raw_get() {
+    let x = UnsafeCell::new(10);
+    let ptr = &x as *const UnsafeCell<i32>;
+    unsafe {
+        // The asserts are repeated in order to ensure that `raw_get()`
+        // is non-mutating.
+        assert_eq!(*UnsafeCell::raw_get(ptr), 10);
+        assert_eq!(*UnsafeCell::raw_get(ptr), 10);
+        *UnsafeCell::raw_get(ptr) += 5;
+        assert_eq!(*UnsafeCell::raw_get(ptr), 15);
+        assert_eq!(*UnsafeCell::raw_get(ptr), 15);
+        assert_eq!(x.into_inner(), 15);
+    }
+}
+
 #[test]
 fn smoketest_cell() {
     let x = Cell::new(10);
index 13f483f19b770fcbc54a2e2fb1a644b5fb45205b..19bcc45108dfd5225761723e0c6b7bb64fbb0eaa 100644 (file)
@@ -48,7 +48,6 @@
 #![feature(int_log)]
 #![feature(iter_advance_by)]
 #![feature(iter_partition_in_place)]
-#![feature(iter_intersperse)]
 #![feature(iter_is_partitioned)]
 #![feature(iter_order_by)]
 #![feature(iter_map_while)]
@@ -65,6 +64,7 @@
 #![feature(unsized_tuple_coercion)]
 #![feature(const_option)]
 #![feature(integer_atomics)]
+#![feature(int_roundings)]
 #![feature(slice_group_by)]
 #![feature(trusted_random_access)]
 #![feature(unsize)]
index 51122c11ce1e29bc19a40e37091e4b1bc1b3cf8e..1517e8a952f93b525c90027d248cc609e80a23d7 100644 (file)
@@ -26,10 +26,10 @@ fn checked_log() {
         assert_eq!(i.checked_log(4), None);
     }
     for i in 1..=i16::MAX {
-        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as i16));
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
     }
     for i in 1..=u16::MAX {
-        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u16));
+        assert_eq!(i.checked_log(13), Some((i as f32).log(13.0) as u32));
     }
 }
 
@@ -46,19 +46,19 @@ fn checked_log2() {
     assert_eq!(0i16.checked_log2(), None);
 
     for i in 1..=u8::MAX {
-        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u8));
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
     }
     for i in 1..=u16::MAX {
         // Guard against Android's imprecise f32::log2 implementation.
         if i != 8192 && i != 32768 {
-            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u16));
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
         }
     }
     for i in i8::MIN..=0 {
         assert_eq!(i.checked_log2(), None);
     }
     for i in 1..=i8::MAX {
-        assert_eq!(i.checked_log2(), Some((i as f32).log2() as i8));
+        assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
     }
     for i in i16::MIN..=0 {
         assert_eq!(i.checked_log2(), None);
@@ -66,7 +66,7 @@ fn checked_log2() {
     for i in 1..=i16::MAX {
         // Guard against Android's imprecise f32::log2 implementation.
         if i != 8192 {
-            assert_eq!(i.checked_log2(), Some((i as f32).log2() as i16));
+            assert_eq!(i.checked_log2(), Some((i as f32).log2() as u32));
         }
     }
 }
@@ -75,9 +75,9 @@ fn checked_log2() {
 #[test]
 #[cfg(not(target_os = "android"))]
 fn checked_log2_not_android() {
-    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u16));
-    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u16));
-    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as i16));
+    assert_eq!(8192u16.checked_log2(), Some((8192f32).log2() as u32));
+    assert_eq!(32768u16.checked_log2(), Some((32768f32).log2() as u32));
+    assert_eq!(8192i16.checked_log2(), Some((8192f32).log2() as u32));
 }
 
 #[test]
@@ -91,10 +91,10 @@ fn checked_log10() {
         assert_eq!(i.checked_log10(), None);
     }
     for i in 1..=i16::MAX {
-        assert_eq!(i.checked_log10(), Some((i as f32).log10() as i16));
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
     }
     for i in 1..=u16::MAX {
-        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u16));
+        assert_eq!(i.checked_log10(), Some((i as f32).log10() as u32));
     }
 }
 
index 90c476567844eae873e13efd4dacd8d4091c4bf1..d2d655ea2c75015959b518a695d6b4dd8f63240a 100644 (file)
@@ -289,6 +289,55 @@ fn test_pow() {
                 assert_eq!(r.saturating_pow(3), -8 as $T);
                 assert_eq!(r.saturating_pow(0), 1 as $T);
             }
+
+            #[test]
+            fn test_div_floor() {
+                let a: $T = 8;
+                let b = 3;
+                assert_eq!(a.div_floor(b), 2);
+                assert_eq!(a.div_floor(-b), -3);
+                assert_eq!((-a).div_floor(b), -3);
+                assert_eq!((-a).div_floor(-b), 2);
+            }
+
+            #[test]
+            fn test_div_ceil() {
+                let a: $T = 8;
+                let b = 3;
+                assert_eq!(a.div_ceil(b), 3);
+                assert_eq!(a.div_ceil(-b), -2);
+                assert_eq!((-a).div_ceil(b), -2);
+                assert_eq!((-a).div_ceil(-b), 3);
+            }
+
+            #[test]
+            fn test_next_multiple_of() {
+                assert_eq!((16 as $T).next_multiple_of(8), 16);
+                assert_eq!((23 as $T).next_multiple_of(8), 24);
+                assert_eq!((16 as $T).next_multiple_of(-8), 16);
+                assert_eq!((23 as $T).next_multiple_of(-8), 16);
+                assert_eq!((-16 as $T).next_multiple_of(8), -16);
+                assert_eq!((-23 as $T).next_multiple_of(8), -16);
+                assert_eq!((-16 as $T).next_multiple_of(-8), -16);
+                assert_eq!((-23 as $T).next_multiple_of(-8), -24);
+                assert_eq!(MIN.next_multiple_of(-1), MIN);
+            }
+
+            #[test]
+            fn test_checked_next_multiple_of() {
+                assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
+                assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
+                assert_eq!((16 as $T).checked_next_multiple_of(-8), Some(16));
+                assert_eq!((23 as $T).checked_next_multiple_of(-8), Some(16));
+                assert_eq!((-16 as $T).checked_next_multiple_of(8), Some(-16));
+                assert_eq!((-23 as $T).checked_next_multiple_of(8), Some(-16));
+                assert_eq!((-16 as $T).checked_next_multiple_of(-8), Some(-16));
+                assert_eq!((-23 as $T).checked_next_multiple_of(-8), Some(-24));
+                assert_eq!((1 as $T).checked_next_multiple_of(0), None);
+                assert_eq!(MAX.checked_next_multiple_of(2), None);
+                assert_eq!(MIN.checked_next_multiple_of(-3), None);
+                assert_eq!(MIN.checked_next_multiple_of(-1), Some(MIN));
+            }
         }
     };
 }
index 445f8fb350eebe24db114f45012111427efa29f1..49f8f1f13fad46ffc0a79fd228b5e4f8bbf0f5e2 100644 (file)
@@ -205,6 +205,31 @@ fn test_pow() {
                 assert_eq!(r.overflowing_pow(2), (1 as $T, true));
                 assert_eq!(r.saturating_pow(2), MAX);
             }
+
+            #[test]
+            fn test_div_floor() {
+                assert_eq!((8 as $T).div_floor(3), 2);
+            }
+
+            #[test]
+            fn test_div_ceil() {
+                assert_eq!((8 as $T).div_ceil(3), 3);
+            }
+
+            #[test]
+            fn test_next_multiple_of() {
+                assert_eq!((16 as $T).next_multiple_of(8), 16);
+                assert_eq!((23 as $T).next_multiple_of(8), 24);
+                assert_eq!(MAX.next_multiple_of(1), MAX);
+            }
+
+            #[test]
+            fn test_checked_next_multiple_of() {
+                assert_eq!((16 as $T).checked_next_multiple_of(8), Some(16));
+                assert_eq!((23 as $T).checked_next_multiple_of(8), Some(24));
+                assert_eq!((1 as $T).checked_next_multiple_of(0), None);
+                assert_eq!(MAX.checked_next_multiple_of(2), None);
+            }
         }
     };
 }
index 43e2af3eb18d262403b9788e5db808a113ee1a64..c591dd3e1a6dbbca75aa3af7e1266f25affae5f0 100644 (file)
@@ -1,5 +1,6 @@
 use core::cell::Cell;
 use core::cmp::Ordering;
+use core::mem::MaybeUninit;
 use core::result::Result::{Err, Ok};
 
 #[test]
@@ -2144,3 +2145,10 @@ fn foo(x: &Cell<isize>) -> Foo<'_> {
 
     assert_eq!(x.get(), 1);
 }
+
+#[test]
+fn test_slice_fill_with_uninit() {
+    // This should not UB. See #87891
+    let mut a = [MaybeUninit::<u8>::uninit(); 10];
+    a.fill(MaybeUninit::uninit());
+}
index 38291b3f57e433de04f9dde1520641f91fd96603..1b051b0d0f6e5079802b5bf394152ab5284901b5 100644 (file)
@@ -24,7 +24,7 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false,
 
 # Dependencies of the `backtrace` crate
 addr2line = { version = "0.16.0", optional = true, default-features = false }
-rustc-demangle = { version = "0.1.18", features = ['rustc-dep-of-std'] }
+rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
 miniz_oxide = { version = "0.4.0", optional = true, default-features = false }
 [dependencies.object]
 version = "0.26.1"
index a7465200955595eb463a178823e147a325fc4a1f..e343073d2150879d87cab768a35cece48d98510f 100644 (file)
@@ -616,6 +616,9 @@ pub fn temp_dir() -> PathBuf {
 /// return the path of the symbolic link and other platforms will return the
 /// path of the symbolic link’s target.
 ///
+/// If the executable is renamed while it is running, platforms may return the
+/// path at the time it was loaded instead of the new path.
+///
 /// # Errors
 ///
 /// Acquiring the path of the current executable is a platform-specific operation
index 0d082648591cef1986dc3041c804aae4ebbd2633..de05c377852950120a0d70655d2ab94c87a53248 100644 (file)
@@ -958,7 +958,7 @@ fn from(s: &CStr) -> Arc<CStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<CString> for Rc<CStr> {
-    /// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
+    /// Converts a [`CString`] into an [`Rc`]`<CStr>` without copying or allocating.
     #[inline]
     fn from(s: CString) -> Rc<CStr> {
         let rc: Rc<[u8]> = Rc::from(s.into_inner());
index f05295f89af1f03997ad8e0491ba151ca22ecd4a..21f354caf6ae9fba2d1ed486ff7411a5dec7e9ea 100644 (file)
@@ -916,7 +916,7 @@ fn from(s: &OsStr) -> Arc<OsStr> {
 
 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
 impl From<OsString> for Rc<OsStr> {
-    /// Converts an [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
+    /// Converts an [`OsString`] into an [`Rc`]`<OsStr>` without copying or allocating.
     #[inline]
     fn from(s: OsString) -> Rc<OsStr> {
         let rc = s.inner.into_rc();
index 9da5fbff9cf0295184d13e57e01b5a0d483a2fed..df60af7c36a3e236a73c6fb8abef22fd217fa989 100644 (file)
@@ -323,7 +323,6 @@ pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(bufwriter_into_parts)]
     /// use std::io::{BufWriter, Write};
     ///
     /// let mut buffer = [0u8; 10];
@@ -334,7 +333,7 @@ pub fn into_inner(mut self) -> Result<W, IntoInnerError<BufWriter<W>>> {
     /// assert_eq!(recovered_writer.len(), 0);
     /// assert_eq!(&buffered_data.unwrap(), b"ata");
     /// ```
-    #[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+    #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
     pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
         let buf = mem::take(&mut self.buf);
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
@@ -444,14 +443,13 @@ fn spare_capacity(&self) -> usize {
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 /// Error returned for the buffered data from `BufWriter::into_parts`, when the underlying
 /// writer has previously panicked.  Contains the (possibly partly written) buffered data.
 ///
 /// # Example
 ///
 /// ```
-/// #![feature(bufwriter_into_parts)]
 /// use std::io::{self, BufWriter, Write};
 /// use std::panic::{catch_unwind, AssertUnwindSafe};
 ///
@@ -478,7 +476,7 @@ pub struct WriterPanicked {
 impl WriterPanicked {
     /// Returns the perhaps-unwritten data.  Some of this data may have been written by the
     /// panicking call(s) to the underlying writer, so simply writing it again is not a good idea.
-    #[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+    #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
     pub fn into_inner(self) -> Vec<u8> {
         self.buf
     }
@@ -487,7 +485,7 @@ pub fn into_inner(self) -> Vec<u8> {
         "BufWriter inner writer panicked, what data remains unwritten is not known";
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl error::Error for WriterPanicked {
     #[allow(deprecated, deprecated_in_future)]
     fn description(&self) -> &str {
@@ -495,14 +493,14 @@ fn description(&self) -> &str {
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl fmt::Display for WriterPanicked {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", Self::DESCRIPTION)
     }
 }
 
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl fmt::Debug for WriterPanicked {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("WriterPanicked")
index 8cfffc2fd35a4e32ccd0faefa36be2c8089677ae..179bdf7fe553ace0281075792757ef91e7ddd7a8 100644 (file)
@@ -14,7 +14,7 @@
 
 pub use bufreader::BufReader;
 pub use bufwriter::BufWriter;
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 pub use bufwriter::WriterPanicked;
 pub use linewriter::LineWriter;
 use linewritershim::LineWriterShim;
index 829ef3d98bbc92b5dd690476dbcb57c7a86f8851..51666c0a3c7f1bf534c653b48916c51c7314bc6c 100644 (file)
@@ -261,19 +261,15 @@ pub enum ErrorKind {
     #[stable(feature = "rust1", since = "1.0.0")]
     Interrupted,
 
-    /// A custom error that does not fall under any other I/O error kind.
-    ///
-    /// This can be used to construct your own [`Error`]s that do not match any
-    /// [`ErrorKind`].
-    ///
-    /// This [`ErrorKind`] is not used by the standard library.
+    /// This operation is unsupported on this platform.
     ///
-    /// Errors from the standard library that do not fall under any of the I/O
-    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
-    /// New [`ErrorKind`]s might be added in the future for some of those.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    Other,
+    /// This means that the operation can never succeed.
+    #[stable(feature = "unsupported_error", since = "1.53.0")]
+    Unsupported,
 
+    // ErrorKinds which are primarily categorisations for OS error
+    // codes should be added above.
+    //
     /// An error returned when an operation could not be completed because an
     /// "end of file" was reached prematurely.
     ///
@@ -283,17 +279,28 @@ pub enum ErrorKind {
     #[stable(feature = "read_exact", since = "1.6.0")]
     UnexpectedEof,
 
-    /// This operation is unsupported on this platform.
-    ///
-    /// This means that the operation can never succeed.
-    #[stable(feature = "unsupported_error", since = "1.53.0")]
-    Unsupported,
-
     /// An operation could not be completed, because it failed
     /// to allocate enough memory.
     #[stable(feature = "out_of_memory_error", since = "1.54.0")]
     OutOfMemory,
 
+    // "Unusual" error kinds which do not correspond simply to (sets
+    // of) OS error codes, should be added just above this comment.
+    // `Other` and `Uncategorised` should remain at the end:
+    //
+    /// A custom error that does not fall under any other I/O error kind.
+    ///
+    /// This can be used to construct your own [`Error`]s that do not match any
+    /// [`ErrorKind`].
+    ///
+    /// This [`ErrorKind`] is not used by the standard library.
+    ///
+    /// Errors from the standard library that do not fall under any of the I/O
+    /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern.
+    /// New [`ErrorKind`]s might be added in the future for some of those.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    Other,
+
     /// Any I/O error from the standard library that's not part of this list.
     ///
     /// Errors that are `Uncategorized` now may move to a different or a new
@@ -307,13 +314,13 @@ pub enum ErrorKind {
 impl ErrorKind {
     pub(crate) fn as_str(&self) -> &'static str {
         use ErrorKind::*;
+        // Strictly alphabetical, please.  (Sadly rustfmt cannot do this yet.)
         match *self {
             AddrInUse => "address in use",
             AddrNotAvailable => "address not available",
             AlreadyExists => "entity already exists",
             ArgumentListTooLong => "argument list too long",
             BrokenPipe => "broken pipe",
-            ResourceBusy => "resource busy",
             ConnectionAborted => "connection aborted",
             ConnectionRefused => "connection refused",
             ConnectionReset => "connection reset",
@@ -321,9 +328,10 @@ pub(crate) fn as_str(&self) -> &'static str {
             Deadlock => "deadlock",
             DirectoryNotEmpty => "directory not empty",
             ExecutableFileBusy => "executable file busy",
+            FileTooLarge => "file too large",
             FilenameTooLong => "filename too long",
+            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
             FilesystemQuotaExceeded => "filesystem quota exceeded",
-            FileTooLarge => "file too large",
             HostUnreachable => "host unreachable",
             Interrupted => "operation interrupted",
             InvalidData => "invalid data",
@@ -332,16 +340,16 @@ pub(crate) fn as_str(&self) -> &'static str {
             NetworkDown => "network down",
             NetworkUnreachable => "network unreachable",
             NotADirectory => "not a directory",
-            StorageFull => "no storage space",
             NotConnected => "not connected",
             NotFound => "entity not found",
+            NotSeekable => "seek on unseekable file",
             Other => "other error",
             OutOfMemory => "out of memory",
             PermissionDenied => "permission denied",
             ReadOnlyFilesystem => "read-only filesystem or storage medium",
+            ResourceBusy => "resource busy",
             StaleNetworkFileHandle => "stale network file handle",
-            FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
-            NotSeekable => "seek on unseekable file",
+            StorageFull => "no storage space",
             TimedOut => "timed out",
             TooManyLinks => "too many links",
             Uncategorized => "uncategorized error",
index 28254fea0d374209395981ea877ecf9339418285..e8466fa06b899470cb213eb6ea295fdc1d6d86b6 100644 (file)
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::buffered::IntoInnerError;
-#[unstable(feature = "bufwriter_into_parts", issue = "80690")]
+#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 pub use self::buffered::WriterPanicked;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::buffered::{BufReader, BufWriter, LineWriter};
index 5e91a0cdbd6b54cf6b2b3636f503e641b55741a7..3a1eb625b57c3d6295defa621d8517096c4974b6 100644 (file)
 #![feature(const_ip)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
+#![feature(const_option)]
 #![feature(const_raw_ptr_deref)]
 #![feature(const_socketaddr)]
 #![feature(const_trait_impl)]
 #![feature(ptr_internals)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
+#![feature(saturating_div)]
+#![feature(saturating_int_impl)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
 #![feature(try_reserve)]
 #![feature(try_reserve_kind)]
 #![feature(unboxed_closures)]
-#![feature(unsafe_cell_raw_get)]
 #![feature(unwrap_infallible)]
 #![feature(vec_into_raw_parts)]
 #![feature(vec_spare_capacity)]
index 336891ec1eb9479ff5b8bd097eced0db91d6c785..5b4a9fa7979de644cb0cc043114071cc53dfb480 100644 (file)
@@ -401,6 +401,53 @@ pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.peek(buf)
     }
 
+    /// Sets the value of the `SO_LINGER` option on this socket.
+    ///
+    /// This value controls how the socket is closed when data remains
+    /// to be sent. If `SO_LINGER` is set, the socket will remain open
+    /// for the specified duration as the system attempts to send pending data.
+    /// Otherwise, the system may close the socket immediately, or wait for a
+    /// default timeout.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(tcp_linger)]
+    ///
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080")
+    ///                        .expect("Couldn't connect to the server...");
+    /// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
+    /// ```
+    #[unstable(feature = "tcp_linger", issue = "88494")]
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        self.0.set_linger(linger)
+    }
+
+    /// Gets the value of the `SO_LINGER` option on this socket.
+    ///
+    /// For more information about this option, see [`TcpStream::set_linger`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(tcp_linger)]
+    ///
+    /// use std::net::TcpStream;
+    /// use std::time::Duration;
+    ///
+    /// let stream = TcpStream::connect("127.0.0.1:8080")
+    ///                        .expect("Couldn't connect to the server...");
+    /// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
+    /// assert_eq!(stream.linger().unwrap(), Some(Duration::from_secs(0)));
+    /// ```
+    #[unstable(feature = "tcp_linger", issue = "88494")]
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        self.0.linger()
+    }
+
     /// Sets the value of the `TCP_NODELAY` option on this socket.
     ///
     /// If set, this option disables the Nagle algorithm. This means that
index 387a3617e5e9a9de55bc567d5d8c74acef196e27..c2061c1351262595cf9f9d804da9a87f1a606f0e 100644 (file)
@@ -767,6 +767,21 @@ fn test_timeout_zero_duration() {
     drop(listener);
 }
 
+#[test]
+#[cfg_attr(target_env = "sgx", ignore)]
+fn linger() {
+    let addr = next_test_ip4();
+    let _listener = t!(TcpListener::bind(&addr));
+
+    let stream = t!(TcpStream::connect(&("localhost", addr.port())));
+
+    assert_eq!(None, t!(stream.linger()));
+    t!(stream.set_linger(Some(Duration::from_secs(1))));
+    assert_eq!(Some(Duration::from_secs(1)), t!(stream.linger()));
+    t!(stream.set_linger(None));
+    assert_eq!(None, t!(stream.linger()));
+}
+
 #[test]
 #[cfg_attr(target_env = "sgx", ignore)]
 fn nodelay() {
index 871505843af23c5ca513c85c0e45d40d0fe1a382..6354752e64e766c97517bce6f845a994ad1e1228 100644 (file)
@@ -39,7 +39,7 @@
 ///
 /// fn main() -> std::io::Result<()> {
 ///     {
-///         let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
+///         let socket = UdpSocket::bind("127.0.0.1:34254")?;
 ///
 ///         // Receives a single datagram message on the socket. If `buf` is too small to hold
 ///         // the message, it will be cut off.
index e7051f0ce95b24e2610fd14a92c31b7fb6b3bdb5..46064bd2837705eafbc31999ff3b115e38e30f74 100644 (file)
@@ -12,6 +12,8 @@
 #[cfg(test)]
 mod benches;
 
+#[unstable(feature = "saturating_int_impl", issue = "87920")]
+pub use core::num::Saturating;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::num::Wrapping;
 #[stable(feature = "rust1", since = "1.0.0")]
index 50464a050c70688b0112df517e90aef932329d62..1e220ea30ab95390ff83f68e6806c248193ed2e3 100644 (file)
@@ -151,3 +151,17 @@ macro_rules! type_alias {
 #[stable(feature = "raw_os", since = "1.1.0")]
 #[doc(no_inline)]
 pub use core::ffi::c_void;
+
+/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
+///
+/// This type is currently always [`usize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_size_t = usize;
+
+/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
+///
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ssize_t = isize;
index e4ce788f74195cbcdf843367709412004dd4c2c5..6cf37f23c574d745d2c5fccb30f9dbd53a4f0e8f 100644 (file)
@@ -934,7 +934,6 @@ fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(unix_chroot)]
 /// use std::os::unix::fs;
 ///
 /// fn main() -> std::io::Result<()> {
@@ -944,7 +943,7 @@ fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "unix_chroot", issue = "84715")]
+#[stable(feature = "unix_chroot", since = "1.56.0")]
 #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
 pub fn chroot<P: AsRef<Path>>(dir: P) -> io::Result<()> {
     sys::fs::chroot(dir.as_ref())
index b20eafb4d53a59396a629ea903fda96b33e5e7a0..71563a02dcbb931290b75a22c20ed4cc6bc1be80 100644 (file)
@@ -517,11 +517,20 @@ fn is_symlink_file(&self) -> bool {
     }
 }
 
-/// Creates a new file symbolic link on the filesystem.
+/// Creates a new symlink to a non-directory file on the filesystem.
 ///
 /// The `link` path will be a file symbolic link pointing to the `original`
 /// path.
 ///
+/// The `original` path should not be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_dir`] for directories.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```no_run
@@ -537,11 +546,20 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io:
     sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
 }
 
-/// Creates a new directory symlink on the filesystem.
+/// Creates a new symlink to a directory on the filesystem.
 ///
 /// The `link` path will be a directory symbolic link pointing to the `original`
 /// path.
 ///
+/// The `original` path must be a directory or a symlink to a directory,
+/// otherwise the symlink will be broken. Use [`symlink_file`] for other files.
+///
+/// This function currently corresponds to [`CreateSymbolicLinkW`][CreateSymbolicLinkW].
+/// Note that this [may change in the future][changes].
+///
+/// [CreateSymbolicLinkW]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
+/// [changes]: io#platform-specific-behavior
+///
 /// # Examples
 ///
 /// ```no_run
index dc4572cd9363b04fa8c7adac5b576f504879c7af..b85489dabe94c716d47b336f3b2387ced963737b 100644 (file)
@@ -3,16 +3,16 @@
 #[doc(alias = "false")]
 /// The boolean type.
 ///
-/// The `bool` represents a value, which could only be either `true` or `false`. If you cast
-/// a `bool` into an integer, `true` will be 1 and `false` will be 0.
+/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast
+/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0.
 ///
 /// # Basic usage
 ///
 /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
 /// which allow us to perform boolean operations using `&`, `|` and `!`.
 ///
-/// `if` requires a `bool` value as its conditional. [`assert!`], which is an
-/// important macro in testing, checks whether an expression is `true` and panics
+/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is [`true`] and panics
 /// if it isn't.
 ///
 /// ```
 /// assert!(!bool_val);
 /// ```
 ///
+/// [`true`]: keyword.true.html
+/// [`false`]: keyword.false.html
 /// [`BitAnd`]: ops::BitAnd
 /// [`BitOr`]: ops::BitOr
 /// [`Not`]: ops::Not
+/// [`if`]: keyword.if.html
 ///
 /// # Examples
 ///
@@ -574,13 +577,15 @@ mod prim_pointer {}
 ///
 /// # Editions
 ///
-/// Prior to Rust 1.53, arrays did not implement `IntoIterator` by value, so the method call
-/// `array.into_iter()` auto-referenced into a slice iterator. Right now, the old behavior
+/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old behavior
 /// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
 /// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition
 /// might be made consistent to the behavior of later editions.
 ///
 /// ```rust,edition2018
+/// // Rust 2015 and 2018:
+///
 /// # #![allow(array_into_iter)] // override our `deny(warnings)`
 /// let array: [i32; 3] = [0; 3];
 ///
@@ -604,11 +609,13 @@ mod prim_pointer {}
 /// }
 /// ```
 ///
-/// Starting in the 2021 edition, `array.into_iter()` will use `IntoIterator` normally to iterate
+/// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate
 /// by value, and `iter()` should be used to iterate by reference like previous editions.
 ///
-/// ```rust,edition2021,ignore
-/// # // FIXME: ignored because 2021 testing is still unstable
+#[cfg_attr(bootstrap, doc = "```rust,edition2021,ignore")]
+#[cfg_attr(not(bootstrap), doc = "```rust,edition2021")]
+/// // Rust 2021:
+///
 /// let array: [i32; 3] = [0; 3];
 ///
 /// // This iterates by reference:
@@ -631,12 +638,12 @@ mod prim_pointer {}
 /// avoid the `into_iter` syntax on those editions. If an edition update is not
 /// viable/desired, there are multiple alternatives:
 /// * use `iter`, equivalent to the old behavior, creating references
-/// * use [`array::IntoIter`], equivalent to the post-2021 behavior (Rust 1.51+)
+/// * use [`IntoIterator::into_iter`], equivalent to the post-2021 behavior (Rust 1.53+)
 /// * replace `for ... in array.into_iter() {` with `for ... in array {`,
 ///   equivalent to the post-2021 behavior (Rust 1.53+)
 ///
 /// ```rust,edition2018
-/// use std::array::IntoIter;
+/// // Rust 2015 and 2018:
 ///
 /// let array: [i32; 3] = [0; 3];
 ///
@@ -647,7 +654,7 @@ mod prim_pointer {}
 /// }
 ///
 /// // This iterates by value:
-/// for item in IntoIter::new(array) {
+/// for item in IntoIterator::into_iter(array) {
 ///     let x: i32 = item;
 ///     println!("{}", x);
 /// }
@@ -660,7 +667,7 @@ mod prim_pointer {}
 ///
 /// // IntoIter can also start a chain.
 /// // This iterates by value:
-/// for item in IntoIter::new(array).enumerate() {
+/// for item in IntoIterator::into_iter(array).enumerate() {
 ///     let (i, x): (usize, i32) = item;
 ///     println!("array[{}] = {}", i, x);
 /// }
@@ -829,7 +836,7 @@ mod prim_str {}
 /// ```
 ///
 /// The sequential nature of the tuple applies to its implementations of various
-/// traits.  For example, in `PartialOrd` and `Ord`, the elements are compared
+/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared
 /// sequentially until the first non-equal set is found.
 ///
 /// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
@@ -1033,14 +1040,16 @@ mod prim_usize {}
 /// References, both shared and mutable.
 ///
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
-/// operators on a value, or by using a `ref` or `ref mut` pattern.
+/// operators on a value, or by using a [`ref`](keyword.ref.html) or
+/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
 ///
 /// For those familiar with pointers, a reference is just a pointer that is assumed to be
 /// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
-/// `&bool` can only point to an allocation containing the integer values `1` (`true`) or `0`
-/// (`false`), but creating a `&bool` that points to an allocation containing
-/// the value `3` causes undefined behaviour.
-/// In fact, `Option<&T>` has the same memory representation as a
+/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
+/// ([`true`](keyword.true.html)) or `0` ([`false`](keyword.false.html)), but creating a
+/// <code>&[bool]</code> that points to an allocation containing the value `3` causes
+/// undefined behaviour.
+/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
 /// nullable but aligned pointer, and can be passed across FFI boundaries as such.
 ///
 /// In most cases, references can be used much like the original value. Field access, method
@@ -1136,7 +1145,7 @@ mod prim_usize {}
 /// * [`ExactSizeIterator`]
 /// * [`FusedIterator`]
 /// * [`TrustedLen`]
-/// * [`Send`] \(note that `&T` references only get `Send` if `T: Sync`)
+/// * [`Send`] \(note that `&T` references only get `Send` if <code>T: [Sync]</code>)
 /// * [`io::Write`]
 /// * [`Read`]
 /// * [`Seek`]
@@ -1168,7 +1177,8 @@ mod prim_ref {}
 /// Function pointers are pointers that point to *code*, not data. They can be called
 /// just like functions. Like references, function pointers are, among other things, assumed to
 /// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
-/// pointers, make your type `Option<fn()>` with your required signature.
+/// pointers, make your type [`Option<fn()>`](core::option#options-and-pointers-nullable-pointers)
+/// with your required signature.
 ///
 /// ### Safety
 ///
index 3f0c99cf74289c639a6934bff9ab194ca471ee38..880ef678a4f7a2f704635cbdd35dd863cec37bad 100644 (file)
@@ -182,6 +182,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
         Ok(self.clone())
     }
 
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
         abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
             .map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))
index 3a69aa039ef2e703e087245eb37fe21dd8eafcbe..89c5af6124f201bfdb8225a5306b494a4080099b 100644 (file)
@@ -183,6 +183,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
         Ok(self.clone())
     }
 
+    pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+        sgx_ineffective(())
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        sgx_ineffective(None)
+    }
+
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
         sgx_ineffective(())
     }
index 6075eb5c7c58a73266fae59326a7bdfc6605793c..6d7524a733afd85cac14a01793ee06047328f5fc 100644 (file)
@@ -506,7 +506,8 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
             let mut ret = DirEntry { entry: mem::zeroed(), dir: Arc::clone(&self.inner) };
             let mut entry_ptr = ptr::null_mut();
             loop {
-                if readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr) != 0 {
+                let err = readdir64_r(self.inner.dirp.0, &mut ret.entry, &mut entry_ptr);
+                if err != 0 {
                     if entry_ptr.is_null() {
                         // We encountered an error (which will be returned in this iteration), but
                         // we also reached the end of the directory stream. The `end_of_stream`
@@ -514,7 +515,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
                         // (instead of looping forever)
                         self.end_of_stream = true;
                     }
-                    return Some(Err(Error::last_os_error()));
+                    return Some(Err(Error::from_raw_os_error(err)));
                 }
                 if entry_ptr.is_null() {
                     return None;
index 3cf637c82285af801e14643a4875b6f19adcd4c1..ba63b41534c1a4f55deca27ad7c99d67ec85158d 100644 (file)
@@ -98,6 +98,14 @@ pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
             unimpl!();
         }
 
+        pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+            unimpl!();
+        }
+
+        pub fn linger(&self) -> io::Result<Option<Duration>> {
+            unimpl!();
+        }
+
         pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
             unimpl!();
         }
@@ -214,6 +222,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
             unimpl!();
         }
 
+        pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+            unimpl!();
+        }
+
+        pub fn linger(&self) -> io::Result<Option<Duration>> {
+            unimpl!();
+        }
+
         pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
             unimpl!();
         }
index c2f5da1dbbb1180cb785cf6691709172a6a065b2..9ae6d12dcb95cfc9a30256f3185db31f74ee7004 100644 (file)
 
 use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
 
+cfg_if::cfg_if! {
+    if #[cfg(target_vendor = "apple")] {
+        use libc::SO_LINGER_SEC as SO_LINGER;
+    } else {
+        use libc::SO_LINGER;
+    }
+}
+
 pub use crate::sys::{cvt, cvt_r};
 
 #[allow(unused_extern_crates)]
@@ -376,6 +384,21 @@ pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         Ok(())
     }
 
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        let linger = libc::linger {
+            l_onoff: linger.is_some() as libc::c_int,
+            l_linger: linger.unwrap_or_default().as_secs() as libc::c_int,
+        };
+
+        setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger)
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?;
+
+        Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
+    }
+
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
     }
index 81f47a779d33b46e94f4c92b172c07560bb552f3..e8747e39bcbf4f1cf81f108c3eaf0e4827dd1435 100644 (file)
@@ -161,24 +161,10 @@ unsafe fn get_stackp() -> *mut libc::c_void {
         stackp.add(page_size())
     }
 
-    #[cfg(any(
-        target_os = "linux",
-        target_os = "macos",
-        target_os = "freebsd",
-        target_os = "netbsd",
-        target_os = "openbsd",
-        target_os = "solaris",
-        target_os = "illumos"
-    ))]
     unsafe fn get_stack() -> libc::stack_t {
         libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
     }
 
-    #[cfg(target_os = "dragonfly")]
-    unsafe fn get_stack() -> libc::stack_t {
-        libc::stack_t { ss_sp: get_stackp() as *mut i8, ss_flags: 0, ss_size: SIGSTKSZ }
-    }
-
     pub unsafe fn make_handler() -> Handler {
         if !NEED_ALTSTACK.load(Ordering::Relaxed) {
             return Handler::null();
index 96203c74b576cf48bd735f7275de7a1a38ea0817..dbb6ce22c22de18cd99c6df1483a4efeb2e835cc 100644 (file)
@@ -76,6 +76,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
         self.0
     }
 
+    pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+        self.0
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        self.0
+    }
+
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
         self.0
     }
index c7c4a9f6efdfb8fad71c442251e61be3ea0990d0..a4dbb225376eee1d7e0b0c63fcf65ae80cd6450e 100644 (file)
@@ -127,6 +127,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
         unsupported()
     }
 
+    pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
+        unsupported()
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        unsupported()
+    }
+
     pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
         unsupported()
     }
index f1264130faf7abe64148586f4ab2ecd52efc365e..3919025b0800663c3b37e749daa27b8ba47915d0 100644 (file)
@@ -1,13 +1,18 @@
-#![allow(dead_code)] // runtime init functions not used during testing
+//! The Windows command line is just a string
+//! <https://docs.microsoft.com/en-us/archive/blogs/larryosterman/the-windows-command-line-is-just-a-string>
+//!
+//! This module implements the parsing necessary to turn that string into a list of arguments.
 
 #[cfg(test)]
 mod tests;
 
 use crate::ffi::OsString;
 use crate::fmt;
+use crate::marker::PhantomData;
+use crate::num::NonZeroU16;
 use crate::os::windows::prelude::*;
 use crate::path::PathBuf;
-use crate::slice;
+use crate::ptr::NonNull;
 use crate::sys::c;
 use crate::sys::windows::os::current_exe;
 use crate::vec;
 use core::iter;
 
 pub fn args() -> Args {
+    // SAFETY: `GetCommandLineW` returns a pointer to a null terminated UTF-16
+    // string so it's safe for `WStrUnits` to use.
     unsafe {
         let lp_cmd_line = c::GetCommandLineW();
-        let parsed_args_list = parse_lp_cmd_line(lp_cmd_line as *const u16, || {
+        let parsed_args_list = parse_lp_cmd_line(WStrUnits::new(lp_cmd_line), || {
             current_exe().map(PathBuf::into_os_string).unwrap_or_else(|_| OsString::new())
         });
 
@@ -28,129 +35,120 @@ pub fn args() -> Args {
 /// Implements the Windows command-line argument parsing algorithm.
 ///
 /// Microsoft's documentation for the Windows CLI argument format can be found at
-/// <https://docs.microsoft.com/en-us/previous-versions//17w5ykft(v=vs.85)>.
+/// <https://docs.microsoft.com/en-us/cpp/cpp/main-function-command-line-args?view=msvc-160#parsing-c-command-line-arguments>
 ///
-/// Windows includes a function to do this in shell32.dll,
-/// but linking with that DLL causes the process to be registered as a GUI application.
+/// A more in-depth explanation is here:
+/// <https://daviddeley.com/autohotkey/parameters/parameters.htm#WIN>
+///
+/// Windows includes a function to do command line parsing in shell32.dll.
+/// However, this is not used for two reasons:
+///
+/// 1. Linking with that DLL causes the process to be registered as a GUI application.
 /// GUI applications add a bunch of overhead, even if no windows are drawn. See
 /// <https://randomascii.wordpress.com/2018/12/03/a-not-called-function-can-cause-a-5x-slowdown/>.
 ///
-/// This function was tested for equivalence to the shell32.dll implementation in
-/// Windows 10 Pro v1803, using an exhaustive test suite available at
-/// <https://gist.github.com/notriddle/dde431930c392e428055b2dc22e638f5> or
-/// <https://paste.gg/p/anonymous/47d6ed5f5bd549168b1c69c799825223>.
-unsafe fn parse_lp_cmd_line<F: Fn() -> OsString>(
-    lp_cmd_line: *const u16,
+/// 2. It does not follow the modern C/C++ argv rules outlined in the first two links above.
+///
+/// This function was tested for equivalence to the C/C++ parsing rules using an
+/// extensive test suite available at
+/// <https://github.com/ChrisDenton/winarg/tree/std>.
+fn parse_lp_cmd_line<'a, F: Fn() -> OsString>(
+    lp_cmd_line: Option<WStrUnits<'a>>,
     exe_name: F,
 ) -> Vec<OsString> {
-    const BACKSLASH: u16 = '\\' as u16;
-    const QUOTE: u16 = '"' as u16;
-    const TAB: u16 = '\t' as u16;
-    const SPACE: u16 = ' ' as u16;
+    const BACKSLASH: NonZeroU16 = NonZeroU16::new(b'\\' as u16).unwrap();
+    const QUOTE: NonZeroU16 = NonZeroU16::new(b'"' as u16).unwrap();
+    const TAB: NonZeroU16 = NonZeroU16::new(b'\t' as u16).unwrap();
+    const SPACE: NonZeroU16 = NonZeroU16::new(b' ' as u16).unwrap();
+
     let mut ret_val = Vec::new();
-    if lp_cmd_line.is_null() || *lp_cmd_line == 0 {
+    // If the cmd line pointer is null or it points to an empty string then
+    // return the name of the executable as argv[0].
+    if lp_cmd_line.as_ref().and_then(|cmd| cmd.peek()).is_none() {
         ret_val.push(exe_name());
         return ret_val;
     }
-    let mut cmd_line = {
-        let mut end = 0;
-        while *lp_cmd_line.offset(end) != 0 {
-            end += 1;
-        }
-        slice::from_raw_parts(lp_cmd_line, end as usize)
-    };
+    let mut code_units = lp_cmd_line.unwrap();
+
     // The executable name at the beginning is special.
-    cmd_line = match cmd_line[0] {
-        // The executable name ends at the next quote mark,
-        // no matter what.
-        QUOTE => {
-            let args = {
-                let mut cut = cmd_line[1..].splitn(2, |&c| c == QUOTE);
-                if let Some(exe) = cut.next() {
-                    ret_val.push(OsString::from_wide(exe));
-                }
-                cut.next()
-            };
-            if let Some(args) = args {
-                args
-            } else {
-                return ret_val;
-            }
-        }
-        // Implement quirk: when they say whitespace here,
-        // they include the entire ASCII control plane:
-        // "However, if lpCmdLine starts with any amount of whitespace, CommandLineToArgvW
-        // will consider the first argument to be an empty string. Excess whitespace at the
-        // end of lpCmdLine is ignored."
-        0..=SPACE => {
-            ret_val.push(OsString::new());
-            &cmd_line[1..]
-        }
-        // The executable name ends at the next whitespace,
-        // no matter what.
-        _ => {
-            let args = {
-                let mut cut = cmd_line.splitn(2, |&c| c > 0 && c <= SPACE);
-                if let Some(exe) = cut.next() {
-                    ret_val.push(OsString::from_wide(exe));
-                }
-                cut.next()
-            };
-            if let Some(args) = args {
-                args
-            } else {
-                return ret_val;
-            }
+    let mut in_quotes = false;
+    let mut cur = Vec::new();
+    for w in &mut code_units {
+        match w {
+            // A quote mark always toggles `in_quotes` no matter what because
+            // there are no escape characters when parsing the executable name.
+            QUOTE => in_quotes = !in_quotes,
+            // If not `in_quotes` then whitespace ends argv[0].
+            SPACE | TAB if !in_quotes => break,
+            // In all other cases the code unit is taken literally.
+            _ => cur.push(w.get()),
         }
-    };
+    }
+    // Skip whitespace.
+    code_units.advance_while(|w| w == SPACE || w == TAB);
+    ret_val.push(OsString::from_wide(&cur));
+
+    // Parse the arguments according to these rules:
+    // * All code units are taken literally except space, tab, quote and backslash.
+    // * When not `in_quotes`, space and tab separate arguments. Consecutive spaces and tabs are
+    // treated as a single separator.
+    // * A space or tab `in_quotes` is taken literally.
+    // * A quote toggles `in_quotes` mode unless it's escaped. An escaped quote is taken literally.
+    // * A quote can be escaped if preceded by an odd number of backslashes.
+    // * If any number of backslashes is immediately followed by a quote then the number of
+    // backslashes is halved (rounding down).
+    // * Backslashes not followed by a quote are all taken literally.
+    // * If `in_quotes` then a quote can also be escaped using another quote
+    // (i.e. two consecutive quotes become one literal quote).
     let mut cur = Vec::new();
     let mut in_quotes = false;
-    let mut was_in_quotes = false;
-    let mut backslash_count: usize = 0;
-    for &c in cmd_line {
-        match c {
-            // backslash
-            BACKSLASH => {
-                backslash_count += 1;
-                was_in_quotes = false;
+    while let Some(w) = code_units.next() {
+        match w {
+            // If not `in_quotes`, a space or tab ends the argument.
+            SPACE | TAB if !in_quotes => {
+                ret_val.push(OsString::from_wide(&cur[..]));
+                cur.truncate(0);
+
+                // Skip whitespace.
+                code_units.advance_while(|w| w == SPACE || w == TAB);
             }
-            QUOTE if backslash_count % 2 == 0 => {
-                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
-                backslash_count = 0;
-                if was_in_quotes {
-                    cur.push('"' as u16);
-                    was_in_quotes = false;
+            // Backslashes can escape quotes or backslashes but only if consecutive backslashes are followed by a quote.
+            BACKSLASH => {
+                let backslash_count = code_units.advance_while(|w| w == BACKSLASH) + 1;
+                if code_units.peek() == Some(QUOTE) {
+                    cur.extend(iter::repeat(BACKSLASH.get()).take(backslash_count / 2));
+                    // The quote is escaped if there are an odd number of backslashes.
+                    if backslash_count % 2 == 1 {
+                        code_units.next();
+                        cur.push(QUOTE.get());
+                    }
                 } else {
-                    was_in_quotes = in_quotes;
-                    in_quotes = !in_quotes;
+                    // If there is no quote on the end then there is no escaping.
+                    cur.extend(iter::repeat(BACKSLASH.get()).take(backslash_count));
                 }
             }
-            QUOTE if backslash_count % 2 != 0 => {
-                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count / 2));
-                backslash_count = 0;
-                was_in_quotes = false;
-                cur.push(b'"' as u16);
-            }
-            SPACE | TAB if !in_quotes => {
-                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
-                if !cur.is_empty() || was_in_quotes {
-                    ret_val.push(OsString::from_wide(&cur[..]));
-                    cur.truncate(0);
+            // If `in_quotes` and not backslash escaped (see above) then a quote either
+            // unsets `in_quote` or is escaped by another quote.
+            QUOTE if in_quotes => match code_units.peek() {
+                // Two consecutive quotes when `in_quotes` produces one literal quote.
+                Some(QUOTE) => {
+                    cur.push(QUOTE.get());
+                    code_units.next();
                 }
-                backslash_count = 0;
-                was_in_quotes = false;
-            }
-            _ => {
-                cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
-                backslash_count = 0;
-                was_in_quotes = false;
-                cur.push(c);
-            }
+                // Otherwise set `in_quotes`.
+                Some(_) => in_quotes = false,
+                // The end of the command line.
+                // Push `cur` even if empty, which we do by breaking while `in_quotes` is still set.
+                None => break,
+            },
+            // If not `in_quotes` and not BACKSLASH escaped (see above) then a quote sets `in_quote`.
+            QUOTE => in_quotes = true,
+            // Everything else is always taken literally.
+            _ => cur.push(w.get()),
         }
     }
-    cur.extend(iter::repeat(b'\\' as u16).take(backslash_count));
-    // include empty quoted strings at the end of the arguments list
-    if !cur.is_empty() || was_in_quotes || in_quotes {
+    // Push the final argument, if any.
+    if !cur.is_empty() || in_quotes {
         ret_val.push(OsString::from_wide(&cur[..]));
     }
     ret_val
@@ -187,3 +185,52 @@ fn len(&self) -> usize {
         self.parsed_args_list.len()
     }
 }
+
+/// A safe iterator over a LPWSTR
+/// (aka a pointer to a series of UTF-16 code units terminated by a NULL).
+struct WStrUnits<'a> {
+    // The pointer must never be null...
+    lpwstr: NonNull<u16>,
+    // ...and the memory it points to must be valid for this lifetime.
+    lifetime: PhantomData<&'a [u16]>,
+}
+impl WStrUnits<'_> {
+    /// Create the iterator. Returns `None` if `lpwstr` is null.
+    ///
+    /// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
+    /// at least as long as the lifetime of this struct.
+    unsafe fn new(lpwstr: *const u16) -> Option<Self> {
+        Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData })
+    }
+    fn peek(&self) -> Option<NonZeroU16> {
+        // SAFETY: It's always safe to read the current item because we don't
+        // ever move out of the array's bounds.
+        unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) }
+    }
+    /// Advance the iterator while `predicate` returns true.
+    /// Returns the number of items it advanced by.
+    fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize {
+        let mut counter = 0;
+        while let Some(w) = self.peek() {
+            if !predicate(w) {
+                break;
+            }
+            counter += 1;
+            self.next();
+        }
+        counter
+    }
+}
+impl Iterator for WStrUnits<'_> {
+    // This can never return zero as that marks the end of the string.
+    type Item = NonZeroU16;
+    fn next(&mut self) -> Option<NonZeroU16> {
+        // SAFETY: If NULL is reached we immediately return.
+        // Therefore it's safe to advance the pointer after that.
+        unsafe {
+            let next = self.peek()?;
+            self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1));
+            Some(next)
+        }
+    }
+}
index 756a4361ea3de31eb0327389591b5e49d9708a93..82c32d08c5ea8f927a576b3b709f04396c621339 100644 (file)
@@ -5,9 +5,9 @@ fn chk(string: &str, parts: &[&str]) {
     let mut wide: Vec<u16> = OsString::from(string).encode_wide().collect();
     wide.push(0);
     let parsed =
-        unsafe { parse_lp_cmd_line(wide.as_ptr() as *const u16, || OsString::from("TEST.EXE")) };
+        unsafe { parse_lp_cmd_line(WStrUnits::new(wide.as_ptr()), || OsString::from("TEST.EXE")) };
     let expected: Vec<OsString> = parts.iter().map(|k| OsString::from(k)).collect();
-    assert_eq!(parsed.as_slice(), expected.as_slice());
+    assert_eq!(parsed.as_slice(), expected.as_slice(), "{:?}", string);
 }
 
 #[test]
@@ -27,35 +27,65 @@ fn single_words() {
 #[test]
 fn official_examples() {
     chk(r#"EXE "abc" d e"#, &["EXE", "abc", "d", "e"]);
-    chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r#"a\\\b"#, "de fg", "h"]);
+    chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r"a\\\b", "de fg", "h"]);
     chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]);
-    chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r#"a\\b c"#, "d", "e"]);
+    chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r"a\\b c", "d", "e"]);
 }
 
 #[test]
 fn whitespace_behavior() {
-    chk(r#" test"#, &["", "test"]);
-    chk(r#"  test"#, &["", "test"]);
-    chk(r#" test test2"#, &["", "test", "test2"]);
-    chk(r#" test  test2"#, &["", "test", "test2"]);
-    chk(r#"test test2 "#, &["test", "test2"]);
-    chk(r#"test  test2 "#, &["test", "test2"]);
-    chk(r#"test "#, &["test"]);
+    chk(" test", &["", "test"]);
+    chk("  test", &["", "test"]);
+    chk(" test test2", &["", "test", "test2"]);
+    chk(" test  test2", &["", "test", "test2"]);
+    chk("test test2 ", &["test", "test2"]);
+    chk("test  test2 ", &["test", "test2"]);
+    chk("test ", &["test"]);
 }
 
 #[test]
 fn genius_quotes() {
     chk(r#"EXE "" """#, &["EXE", "", ""]);
-    chk(r#"EXE "" """"#, &["EXE", "", "\""]);
+    chk(r#"EXE "" """"#, &["EXE", "", r#"""#]);
     chk(
         r#"EXE "this is """all""" in the same argument""#,
-        &["EXE", "this is \"all\" in the same argument"],
+        &["EXE", r#"this is "all" in the same argument"#],
     );
-    chk(r#"EXE "a"""#, &["EXE", "a\""]);
-    chk(r#"EXE "a"" a"#, &["EXE", "a\"", "a"]);
+    chk(r#"EXE "a"""#, &["EXE", r#"a""#]);
+    chk(r#"EXE "a"" a"#, &["EXE", r#"a" a"#]);
     // quotes cannot be escaped in command names
     chk(r#""EXE" check"#, &["EXE", "check"]);
     chk(r#""EXE check""#, &["EXE check"]);
-    chk(r#""EXE """for""" check"#, &["EXE ", r#"for""#, "check"]);
-    chk(r#""EXE \"for\" check"#, &[r#"EXE \"#, r#"for""#, "check"]);
+    chk(r#""EXE """for""" check"#, &["EXE for check"]);
+    chk(r#""EXE \"for\" check"#, &[r"EXE \for\ check"]);
+    chk(r#""EXE \" for \" check"#, &[r"EXE \", "for", r#"""#, "check"]);
+    chk(r#"E"X"E test"#, &["EXE", "test"]);
+    chk(r#"EX""E test"#, &["EXE", "test"]);
+}
+
+// from https://daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESEX
+#[test]
+fn post_2008() {
+    chk("EXE CallMeIshmael", &["EXE", "CallMeIshmael"]);
+    chk(r#"EXE "Call Me Ishmael""#, &["EXE", "Call Me Ishmael"]);
+    chk(r#"EXE Cal"l Me I"shmael"#, &["EXE", "Call Me Ishmael"]);
+    chk(r#"EXE CallMe\"Ishmael"#, &["EXE", r#"CallMe"Ishmael"#]);
+    chk(r#"EXE "CallMe\"Ishmael""#, &["EXE", r#"CallMe"Ishmael"#]);
+    chk(r#"EXE "Call Me Ishmael\\""#, &["EXE", r"Call Me Ishmael\"]);
+    chk(r#"EXE "CallMe\\\"Ishmael""#, &["EXE", r#"CallMe\"Ishmael"#]);
+    chk(r#"EXE a\\\b"#, &["EXE", r"a\\\b"]);
+    chk(r#"EXE "a\\\b""#, &["EXE", r"a\\\b"]);
+    chk(r#"EXE "\"Call Me Ishmael\"""#, &["EXE", r#""Call Me Ishmael""#]);
+    chk(r#"EXE "C:\TEST A\\""#, &["EXE", r"C:\TEST A\"]);
+    chk(r#"EXE "\"C:\TEST A\\\"""#, &["EXE", r#""C:\TEST A\""#]);
+    chk(r#"EXE "a b c"  d  e"#, &["EXE", "a b c", "d", "e"]);
+    chk(r#"EXE "ab\"c"  "\\"  d"#, &["EXE", r#"ab"c"#, r"\", "d"]);
+    chk(r#"EXE a\\\b d"e f"g h"#, &["EXE", r"a\\\b", "de fg", "h"]);
+    chk(r#"EXE a\\\"b c d"#, &["EXE", r#"a\"b"#, "c", "d"]);
+    chk(r#"EXE a\\\\"b c" d e"#, &["EXE", r"a\\b c", "d", "e"]);
+    // Double Double Quotes
+    chk(r#"EXE "a b c"""#, &["EXE", r#"a b c""#]);
+    chk(r#"EXE """CallMeIshmael"""  b  c"#, &["EXE", r#""CallMeIshmael""#, "b", "c"]);
+    chk(r#"EXE """Call Me Ishmael""""#, &["EXE", r#""Call Me Ishmael""#]);
+    chk(r#"EXE """"Call Me Ishmael"" b c"#, &["EXE", r#""Call"#, "Me", "Ishmael", "b", "c"]);
 }
index 63f9be7b7e350d18d1e0a546868a19fdb974fe80..6fb850d182889e7297f931894fa68560a03301b5 100644 (file)
@@ -197,6 +197,7 @@ fn clone(&self) -> Self {
 pub const SOCK_STREAM: c_int = 1;
 pub const SOCKET_ERROR: c_int = -1;
 pub const SOL_SOCKET: c_int = 0xffff;
+pub const SO_LINGER: c_int = 0x0080;
 pub const SO_RCVTIMEO: c_int = 0x1006;
 pub const SO_SNDTIMEO: c_int = 0x1005;
 pub const IPPROTO_IP: c_int = 0;
@@ -216,6 +217,13 @@ fn clone(&self) -> Self {
 pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
 pub const MSG_PEEK: c_int = 0x2;
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct linger {
+    pub l_onoff: c_ushort,
+    pub l_linger: c_ushort,
+}
+
 #[repr(C)]
 pub struct ip_mreq {
     pub imr_multiaddr: in_addr,
@@ -781,7 +789,7 @@ pub fn GetFileInformationByHandleEx(
     pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
     pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL;
     pub fn SetLastError(dwErrCode: DWORD);
-    pub fn GetCommandLineW() -> *mut LPCWSTR;
+    pub fn GetCommandLineW() -> LPWSTR;
     pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD;
     pub fn GetCurrentProcess() -> HANDLE;
     pub fn GetCurrentThread() -> HANDLE;
index 55aacb38c6f785e23a550560db9eb73a8ead6675..33152cc97abc018428c3f2aa7e8f6f4ed808fef2 100644 (file)
@@ -15,7 +15,7 @@
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
-use libc::{c_int, c_long, c_ulong};
+use libc::{c_int, c_long, c_ulong, c_ushort};
 
 pub type wrlen_t = i32;
 
@@ -446,6 +446,21 @@ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         cvt(result).map(drop)
     }
 
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        let linger = c::linger {
+            l_onoff: linger.is_some() as c_ushort,
+            l_linger: linger.unwrap_or_default().as_secs() as c_ushort,
+        };
+
+        net::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        let val: c::linger = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
+
+        Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
+    }
+
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
     }
index 6f2618c63b5d553c1e1d2b380eda5399288e76c1..2719a530dfd41151cd50581889909e312530c2d0 100644 (file)
@@ -9,14 +9,25 @@
 use crate::sys::c;
 use crate::sys::cvt;
 use crate::sys::handle::Handle;
+use core::str::utf8_char_width;
 
 // Don't cache handles but get them fresh for every read/write. This allows us to track changes to
 // the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
 pub struct Stdin {
     surrogate: u16,
 }
-pub struct Stdout;
-pub struct Stderr;
+pub struct Stdout {
+    incomplete_utf8: IncompleteUtf8,
+}
+
+pub struct Stderr {
+    incomplete_utf8: IncompleteUtf8,
+}
+
+struct IncompleteUtf8 {
+    bytes: [u8; 4],
+    len: u8,
+}
 
 // Apparently Windows doesn't handle large reads on stdin or writes to stdout/stderr well (see
 // #13304 for details).
@@ -51,7 +62,15 @@ fn is_console(handle: c::HANDLE) -> bool {
     unsafe { c::GetConsoleMode(handle, &mut mode) != 0 }
 }
 
-fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
+fn write(
+    handle_id: c::DWORD,
+    data: &[u8],
+    incomplete_utf8: &mut IncompleteUtf8,
+) -> io::Result<usize> {
+    if data.is_empty() {
+        return Ok(0);
+    }
+
     let handle = get_handle(handle_id)?;
     if !is_console(handle) {
         unsafe {
@@ -62,22 +81,73 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
         }
     }
 
-    // As the console is meant for presenting text, we assume bytes of `data` come from a string
-    // and are encoded as UTF-8, which needs to be encoded as UTF-16.
+    if incomplete_utf8.len > 0 {
+        assert!(
+            incomplete_utf8.len < 4,
+            "Unexpected number of bytes for incomplete UTF-8 codepoint."
+        );
+        if data[0] >> 6 != 0b10 {
+            // not a continuation byte - reject
+            incomplete_utf8.len = 0;
+            return Err(io::Error::new_const(
+                io::ErrorKind::InvalidData,
+                &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+            ));
+        }
+        incomplete_utf8.bytes[incomplete_utf8.len as usize] = data[0];
+        incomplete_utf8.len += 1;
+        let char_width = utf8_char_width(incomplete_utf8.bytes[0]);
+        if (incomplete_utf8.len as usize) < char_width {
+            // more bytes needed
+            return Ok(1);
+        }
+        let s = str::from_utf8(&incomplete_utf8.bytes[0..incomplete_utf8.len as usize]);
+        incomplete_utf8.len = 0;
+        match s {
+            Ok(s) => {
+                assert_eq!(char_width, s.len());
+                let written = write_valid_utf8_to_console(handle, s)?;
+                assert_eq!(written, s.len()); // guaranteed by write_valid_utf8_to_console() for single codepoint writes
+                return Ok(1);
+            }
+            Err(_) => {
+                return Err(io::Error::new_const(
+                    io::ErrorKind::InvalidData,
+                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                ));
+            }
+        }
+    }
+
+    // As the console is meant for presenting text, we assume bytes of `data` are encoded as UTF-8,
+    // which needs to be encoded as UTF-16.
     //
     // If the data is not valid UTF-8 we write out as many bytes as are valid.
-    // Only when there are no valid bytes (which will happen on the next call), return an error.
+    // If the first byte is invalid it is either first byte of a multi-byte sequence but the
+    // provided byte slice is too short or it is the first byte of an invalide multi-byte sequence.
     let len = cmp::min(data.len(), MAX_BUFFER_SIZE / 2);
     let utf8 = match str::from_utf8(&data[..len]) {
         Ok(s) => s,
         Err(ref e) if e.valid_up_to() == 0 => {
-            return Err(io::Error::new_const(
-                io::ErrorKind::InvalidData,
-                &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
-            ));
+            let first_byte_char_width = utf8_char_width(data[0]);
+            if first_byte_char_width > 1 && data.len() < first_byte_char_width {
+                incomplete_utf8.bytes[0] = data[0];
+                incomplete_utf8.len = 1;
+                return Ok(1);
+            } else {
+                return Err(io::Error::new_const(
+                    io::ErrorKind::InvalidData,
+                    &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences",
+                ));
+            }
         }
         Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(),
     };
+
+    write_valid_utf8_to_console(handle, utf8)
+}
+
+fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> {
     let mut utf16 = [0u16; MAX_BUFFER_SIZE / 2];
     let mut len_utf16 = 0;
     for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) {
@@ -259,15 +329,21 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
     Ok(written)
 }
 
+impl IncompleteUtf8 {
+    pub const fn new() -> IncompleteUtf8 {
+        IncompleteUtf8 { bytes: [0; 4], len: 0 }
+    }
+}
+
 impl Stdout {
     pub const fn new() -> Stdout {
-        Stdout
+        Stdout { incomplete_utf8: IncompleteUtf8::new() }
     }
 }
 
 impl io::Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        write(c::STD_OUTPUT_HANDLE, buf)
+        write(c::STD_OUTPUT_HANDLE, buf, &mut self.incomplete_utf8)
     }
 
     fn flush(&mut self) -> io::Result<()> {
@@ -277,13 +353,13 @@ fn flush(&mut self) -> io::Result<()> {
 
 impl Stderr {
     pub const fn new() -> Stderr {
-        Stderr
+        Stderr { incomplete_utf8: IncompleteUtf8::new() }
     }
 }
 
 impl io::Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        write(c::STD_ERROR_HANDLE, buf)
+        write(c::STD_ERROR_HANDLE, buf, &mut self.incomplete_utf8)
     }
 
     fn flush(&mut self) -> io::Result<()> {
index 0ffa5c01dd33b546eaa9ee6ccba297d19ed859db..c5c3df361f34bf86066eee932b74817ae83f2a43 100644 (file)
@@ -297,6 +297,14 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
         self.inner.duplicate().map(|s| TcpStream { inner: s })
     }
 
+    pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
+        self.inner.set_linger(linger)
+    }
+
+    pub fn linger(&self) -> io::Result<Option<Duration>> {
+        self.inner.linger()
+    }
+
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         self.inner.set_nodelay(nodelay)
     }
index ec105f231e5a75c344327ffe565f06e8d976999c..e9207ee36171b18d44613c17583cf0a77f0232e0 100644 (file)
@@ -1,13 +1,32 @@
 //! Temporal quantification.
 //!
-//! Example:
+//! # Examples:
 //!
+//! There are multiple ways to create a new [`Duration`]:
+//!
+//! ```
+//! # use std::time::Duration;
+//! let five_seconds = Duration::from_secs(5);
+//! assert_eq!(five_seconds, Duration::from_millis(5_000));
+//! assert_eq!(five_seconds, Duration::from_micros(5_000_000));
+//! assert_eq!(five_seconds, Duration::from_nanos(5_000_000_000));
+//!
+//! let ten_seconds = Duration::from_secs(10);
+//! let seven_nanos = Duration::from_nanos(7);
+//! let total = ten_seconds + seven_nanos;
+//! assert_eq!(total, Duration::new(10, 7));
 //! ```
-//! use std::time::Duration;
 //!
-//! let five_seconds = Duration::new(5, 0);
-//! // both declarations are equivalent
-//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
+//! Using [`Instant`] to calculate how long a function took to run:
+//!
+//! ```ignore (incomplete)
+//! let now = Instant::now();
+//!
+//! // Calling a slow function, it may take a while
+//! slow_function();
+//!
+//! let elapsed_time = now.elapsed();
+//! println!("Running slow_function() took {} seconds.", elapsed_time.as_secs());
 //! ```
 
 #![stable(feature = "time", since = "1.3.0")]
@@ -26,7 +45,7 @@
 pub use core::time::Duration;
 
 /// A measurement of a monotonically nondecreasing clock.
-/// Opaque and useful only with `Duration`.
+/// Opaque and useful only with [`Duration`].
 ///
 /// Instants are always guaranteed to be no less than any previously measured
 /// instant when created, and are often useful for tasks such as measuring
index c158cfd38e20d855f5d6ca8a5a101eefb82604a8..89b0e355bc3cff5cddec2290c84f36eb3a026aad 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c158cfd38e20d855f5d6ca8a5a101eefb82604a8
+Subproject commit 89b0e355bc3cff5cddec2290c84f36eb3a026aad
index 0529d24a27408002b3b36c500c9b87b8cd925d62..1d0b4a59a287b05969080147a5aab691d0e36603 100644 (file)
@@ -4,36 +4,18 @@ fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
-    if cfg!(target_os = "linux") && cfg!(feature = "system-llvm-libunwind") {
-        // linking for Linux is handled in lib.rs
-        return;
-    }
-
-    if cfg!(feature = "llvm-libunwind")
-        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
-    {
-        // Build the unwinding from libunwind C/C++ source code.
-        llvm_libunwind::compile();
-    } else if target.contains("x86_64-fortanix-unknown-sgx") {
-        llvm_libunwind::compile();
-    } else if target.contains("linux") {
-        // linking for Linux is handled in lib.rs
-        if target.contains("musl") {
-            llvm_libunwind::compile();
-        } else if target.contains("android") {
-            let build = cc::Build::new();
+    if target.contains("android") {
+        let build = cc::Build::new();
 
-            // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
-            // check if we have `libunwind` available and if so use it. Otherwise
-            // fall back to `libgcc` to support older ndk versions.
-            let has_unwind =
-                build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
+        // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
+        // check if we have `libunwind` available and if so use it. Otherwise
+        // fall back to `libgcc` to support older ndk versions.
+        let has_unwind = build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
 
-            if has_unwind {
-                println!("cargo:rustc-link-lib=unwind");
-            } else {
-                println!("cargo:rustc-link-lib=gcc");
-            }
+        if has_unwind {
+            println!("cargo:rustc-link-lib=unwind");
+        } else {
+            println!("cargo:rustc-link-lib=gcc");
         }
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=gcc_s");
@@ -63,111 +45,3 @@ fn main() {
         // redox is handled in lib.rs
     }
 }
-
-mod llvm_libunwind {
-    use std::env;
-    use std::path::Path;
-
-    /// Compile the libunwind C/C++ source code.
-    pub fn compile() {
-        let target = env::var("TARGET").expect("TARGET was not set");
-        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
-        let mut cc_cfg = cc::Build::new();
-        let mut cpp_cfg = cc::Build::new();
-        let root = Path::new("../../src/llvm-project/libunwind");
-
-        cpp_cfg.cpp(true);
-        cpp_cfg.cpp_set_stdlib(None);
-        cpp_cfg.flag("-nostdinc++");
-        cpp_cfg.flag("-fno-exceptions");
-        cpp_cfg.flag("-fno-rtti");
-        cpp_cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
-
-        // Don't set this for clang
-        // By default, Clang builds C code in GNU C17 mode.
-        // By default, Clang builds C++ code according to the C++98 standard,
-        // with many C++11 features accepted as extensions.
-        if cpp_cfg.get_compiler().is_like_gnu() {
-            cpp_cfg.flag("-std=c++11");
-            cc_cfg.flag("-std=c99");
-        }
-
-        if target.contains("x86_64-fortanix-unknown-sgx") || target_env == "musl" {
-            // use the same GCC C compiler command to compile C++ code so we do not need to setup the
-            // C++ compiler env variables on the builders.
-            // Don't set this for clang++, as clang++ is able to compile this without libc++.
-            if cpp_cfg.get_compiler().is_like_gnu() {
-                cpp_cfg.cpp(false);
-            }
-        }
-
-        for cfg in [&mut cc_cfg, &mut cpp_cfg].iter_mut() {
-            cfg.warnings(false);
-            cfg.flag("-fstrict-aliasing");
-            cfg.flag("-funwind-tables");
-            cfg.flag("-fvisibility=hidden");
-            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
-            cfg.include(root.join("include"));
-            cfg.cargo_metadata(false);
-
-            if target.contains("x86_64-fortanix-unknown-sgx") {
-                cfg.static_flag(true);
-                cfg.opt_level(3);
-                cfg.flag("-fno-stack-protector");
-                cfg.flag("-ffreestanding");
-                cfg.flag("-fexceptions");
-
-                // easiest way to undefine since no API available in cc::Build to undefine
-                cfg.flag("-U_FORTIFY_SOURCE");
-                cfg.define("_FORTIFY_SOURCE", "0");
-                cfg.define("RUST_SGX", "1");
-                cfg.define("__NO_STRING_INLINES", None);
-                cfg.define("__NO_MATH_INLINES", None);
-                cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
-                cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
-                cfg.define("NDEBUG", None);
-            }
-        }
-
-        let mut c_sources = vec![
-            "Unwind-sjlj.c",
-            "UnwindLevel1-gcc-ext.c",
-            "UnwindLevel1.c",
-            "UnwindRegistersRestore.S",
-            "UnwindRegistersSave.S",
-        ];
-
-        let cpp_sources = vec!["Unwind-EHABI.cpp", "Unwind-seh.cpp", "libunwind.cpp"];
-        let cpp_len = cpp_sources.len();
-
-        if target.contains("x86_64-fortanix-unknown-sgx") {
-            c_sources.push("UnwindRustSgx.c");
-        }
-
-        for src in c_sources {
-            cc_cfg.file(root.join("src").join(src).canonicalize().unwrap());
-        }
-
-        for src in cpp_sources {
-            cpp_cfg.file(root.join("src").join(src).canonicalize().unwrap());
-        }
-
-        let out_dir = env::var("OUT_DIR").unwrap();
-        println!("cargo:rustc-link-search=native={}", &out_dir);
-
-        cpp_cfg.compile("unwind-cpp");
-
-        let mut count = 0;
-        for entry in std::fs::read_dir(&out_dir).unwrap() {
-            let obj = entry.unwrap().path().canonicalize().unwrap();
-            if let Some(ext) = obj.extension() {
-                if ext == "o" {
-                    cc_cfg.object(&obj);
-                    count += 1;
-                }
-            }
-        }
-        assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);
-        cc_cfg.compile("unwind");
-    }
-}
index 53b13b9043b3a2e9fef7fe26e318e2f8a83303e4..06384b159264789108eb7329e14b5eb85437e6d4 100644 (file)
@@ -1,6 +1,8 @@
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![feature(link_cfg)]
+#![feature(native_link_modifiers)]
+#![feature(native_link_modifiers_bundle)]
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(static_nobundle)]
     if #[cfg(all(feature = "llvm-libunwind", feature = "system-llvm-libunwind"))] {
         compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time");
     } else if #[cfg(feature = "llvm-libunwind")] {
-        #[link(name = "unwind", kind = "static")]
+        #[link(name = "unwind", kind = "static", modifiers = "-bundle")]
         extern "C" {}
     } else if #[cfg(feature = "system-llvm-libunwind")] {
-        #[link(name = "unwind", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
+        #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
         #[link(name = "unwind", cfg(not(target_feature = "crt-static")))]
         extern "C" {}
     } else {
-        #[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
+        #[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
         #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
         extern "C" {}
     }
 extern "C" {}
 
 #[cfg(target_os = "redox")]
-#[link(name = "gcc_eh", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
+#[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
 #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
 extern "C" {}
 
 #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
-#[link(name = "unwind", kind = "static")]
+#[link(name = "unwind", kind = "static", modifiers = "-bundle")]
 extern "C" {}
index 196be74decba4e4fb9c454f3fdf7a50ede26585e..5e15fe75a2463632f14850d7433168c16936eed8 100644 (file)
@@ -77,9 +77,18 @@ pub enum _Unwind_Context {}
 
 pub type _Unwind_Exception_Cleanup_Fn =
     extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
+
+// FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
+// the block are reexported in dylib build of libstd. This is needed when build rustc with
+// feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols.
+// However the `link` attribute is duplicated multiple times and does not just export symbol,
+// a better way to manually export symbol would be another attribute like `#[export]`.
+// See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module
+// rustc_codegen_ssa::src::back::symbol_export, rustc_middle::middle::exported_symbols
+// and RFC 2841
 #[cfg_attr(
     all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
-    link(name = "unwind", kind = "static")
+    link(name = "unwind", kind = "static", modifiers = "-bundle")
 )]
 extern "C-unwind" {
     pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
@@ -106,9 +115,10 @@ pub enum _Unwind_Action {
     }
     pub use _Unwind_Action::*;
 
-    #[cfg_attr(all(feature = "llvm-libunwind",
-                   any(target_os = "fuchsia", target_os = "linux")),
-               link(name = "unwind", kind = "static"))]
+    #[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_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word;
         pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word);
@@ -163,9 +173,10 @@ enum _Unwind_VRS_DataRepresentation {
     pub const UNWIND_SP_REG: c_int = 13;
     pub const UNWIND_IP_REG: c_int = 15;
 
-    #[cfg_attr(all(feature = "llvm-libunwind",
-                   any(target_os = "fuchsia", target_os = "linux")),
-               link(name = "unwind", kind = "static"))]
+    #[cfg_attr(
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        link(name = "unwind", kind = "static", modifiers = "-bundle")
+    )]
     extern "C" {
         fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
                            regclass: _Unwind_VRS_RegClass,
@@ -228,9 +239,10 @@ pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut c_void {
 cfg_if::cfg_if! {
 if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
     // Not 32-bit iOS
-    #[cfg_attr(all(feature = "llvm-libunwind",
-                   any(target_os = "fuchsia", target_os = "linux")),
-               link(name = "unwind", kind = "static"))]
+    #[cfg_attr(
+        all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux")),
+        link(name = "unwind", kind = "static", modifiers = "-bundle")
+    )]
     extern "C-unwind" {
         pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
@@ -241,9 +253,6 @@ pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
     }
 } else {
     // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
-    #[cfg_attr(all(feature = "llvm-libunwind",
-                   any(target_os = "fuchsia", target_os = "linux")),
-               link(name = "unwind", kind = "static"))]
     extern "C-unwind" {
         pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
     }
index 3faf38c66ec8bb4b4126d686143bbfc1c7bdb87a..e34768bc2c906ba9f3245cc87f7c3508f6e0f559 100644 (file)
@@ -301,6 +301,7 @@ def default_build_triple(verbose):
         'ppc': 'powerpc',
         'ppc64': 'powerpc64',
         'ppc64le': 'powerpc64le',
+        'riscv64': 'riscv64gc',
         's390x': 's390x',
         'x64': 'x86_64',
         'x86': 'i686',
index 4eb335979b983b004efb2a1358a094947f917a64..f5fad4b4136849c8f023eda32bb9d71365f7e1b1 100644 (file)
@@ -107,6 +107,11 @@ fn run(self, builder: &Builder<'_>) {
             add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
         }
 
+        // don't run on std twice with x.py clippy
+        if builder.kind == Kind::Clippy {
+            return;
+        }
+
         // Then run cargo again, once we've put the rmeta files for the library
         // crates into the sysroot. This is needed because e.g., core's tests
         // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
@@ -120,6 +125,7 @@ fn run(self, builder: &Builder<'_>) {
             target,
             cargo_subcommand(builder.kind),
         );
+
         cargo.arg("--all-targets");
         std_cargo(builder, target, compiler.stage, &mut cargo);
 
@@ -192,7 +198,12 @@ fn run(self, builder: &Builder<'_>) {
             cargo_subcommand(builder.kind),
         );
         rustc_cargo(builder, &mut cargo, target);
-        cargo.arg("--all-targets");
+
+        // For ./x.py clippy, don't run with --all-targets because
+        // linting tests and benchmarks can produce very noisy results
+        if builder.kind != Kind::Clippy {
+            cargo.arg("--all-targets");
+        }
 
         // Explicitly pass -p for all compiler krates -- this will force cargo
         // to also check the tests/benches/examples for these crates, rather
@@ -313,7 +324,12 @@ fn run(self, builder: &Builder<'_>) {
                     $source_type,
                     &[],
                 );
-                cargo.arg("--all-targets");
+
+                // For ./x.py clippy, don't run with --all-targets because
+                // linting tests and benchmarks can produce very noisy results
+                if builder.kind != Kind::Clippy {
+                    cargo.arg("--all-targets");
+                }
 
                 // Enable internal lints for clippy and rustdoc
                 // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
index d25989954783ae05ce240f9ffcebf595622e71c7..df9e9bce415276245571bf083e0608ee390e1d88 100644 (file)
@@ -23,7 +23,7 @@
 use crate::builder::Cargo;
 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
-use crate::config::TargetSelection;
+use crate::config::{LlvmLibunwind, TargetSelection};
 use crate::dist;
 use crate::native;
 use crate::tool::SourceType;
@@ -142,6 +142,14 @@ fn copy_and_stamp(
     target_deps.push((target, dependency_type));
 }
 
+fn copy_llvm_libunwind(builder: &Builder<'_>, target: TargetSelection, libdir: &Path) -> PathBuf {
+    let libunwind_path = builder.ensure(native::Libunwind { target });
+    let libunwind_source = libunwind_path.join("libunwind.a");
+    let libunwind_target = libdir.join("libunwind.a");
+    builder.copy(&libunwind_source, &libunwind_target);
+    libunwind_target
+}
+
 /// Copies third party objects needed by various targets.
 fn copy_third_party_objects(
     builder: &Builder<'_>,
@@ -167,6 +175,15 @@ fn copy_third_party_objects(
         );
     }
 
+    if target == "x86_64-fortanix-unknown-sgx"
+        || builder.config.llvm_libunwind == LlvmLibunwind::InTree
+            && (target.contains("linux") || target.contains("fuchsia"))
+    {
+        let libunwind_path =
+            copy_llvm_libunwind(builder, target, &builder.sysroot_libdir(*compiler, target));
+        target_deps.push((libunwind_path, DependencyType::Target));
+    }
+
     target_deps
 }
 
@@ -208,6 +225,9 @@ fn copy_self_contained_objects(
             builder.copy(&src, &target);
             target_deps.push((target, DependencyType::TargetSelfContained));
         }
+
+        let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
+        target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
     } else if target.ends_with("-wasi") {
         let srcdir = builder
             .wasi_root(target)
@@ -1121,6 +1141,10 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
                 &lld_install.join("bin").join(&src_exe),
                 &gcc_ld_dir.join(exe("ld", target_compiler.host)),
             );
+            builder.copy(
+                &lld_install.join("bin").join(&src_exe),
+                &gcc_ld_dir.join(exe("ld64", target_compiler.host)),
+            );
         }
 
         // Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM
index dd536cb7b02bfdc74ba4a23723e7c129ff285e8b..5706b8f9e7cc6055be056ebeb214dd7baae1714c 100644 (file)
@@ -143,6 +143,8 @@ pub struct Config {
     pub rust_new_symbol_mangling: bool,
     pub rust_profile_use: Option<String>,
     pub rust_profile_generate: Option<String>,
+    pub llvm_profile_use: Option<String>,
+    pub llvm_profile_generate: bool,
 
     pub build: TargetSelection,
     pub hosts: Vec<TargetSelection>,
@@ -605,6 +607,8 @@ pub fn parse(args: &[String]) -> Config {
         if let Some(value) = flags.deny_warnings {
             config.deny_warnings = value;
         }
+        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");
index 64075e18366bfbada2f733a93a2b7c3dc6c706c2..7c1bb1a91481bdeb69bfb517bbb4ca170ddba788 100644 (file)
@@ -412,6 +412,8 @@ fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
                 let gcc_lld_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&gcc_lld_dir));
                 builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host)));
+                builder
+                    .copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld64", compiler.host)));
             }
 
             // Copy over llvm-dwp if it's there
@@ -2157,10 +2159,16 @@ fn make_run(run: RunConfig<'_>) {
     }
 
     fn run(self, builder: &Builder<'_>) -> Self::Output {
-        let path = builder.config.rust_profile_use.as_ref()?;
-
+        let mut added_anything = false;
         let tarball = Tarball::new(builder, "reproducible-artifacts", &self.target.triple);
-        tarball.add_file(path, ".", 0o644);
-        Some(tarball.generate())
+        if let Some(path) = builder.config.rust_profile_use.as_ref() {
+            tarball.add_file(path, ".", 0o644);
+            added_anything = true;
+        }
+        if let Some(path) = builder.config.llvm_profile_use.as_ref() {
+            tarball.add_file(path, ".", 0o644);
+            added_anything = true;
+        }
+        if added_anything { Some(tarball.generate()) } else { None }
     }
 }
index fb5b058cb4d74a46c6e4de30695d020f9a834a93..19e5fffcc2ddb1d3b267862a465961996b09ab46 100644 (file)
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/80932
+Last change is for: https://github.com/rust-lang/rust/pull/88069
index 80c33fa4d7c9700de0323e21598589e4179bfd84..2fddda74a28e924bfd3e7db776bdc38e67a15933 100644 (file)
@@ -71,6 +71,13 @@ pub struct Flags {
 
     pub rust_profile_use: Option<String>,
     pub rust_profile_generate: Option<String>,
+
+    pub llvm_profile_use: Option<String>,
+    // LLVM doesn't support a custom location for generating profile
+    // information.
+    //
+    // llvm_out/build/profiles/ is the location this writes to.
+    pub llvm_profile_generate: bool,
 }
 
 pub enum Subcommand {
@@ -222,8 +229,15 @@ pub fn parse(args: &[String]) -> Flags {
              VALUE overrides the skip-rebuild option in config.toml.",
             "VALUE",
         );
-        opts.optopt("", "rust-profile-generate", "generate PGO profile with rustc build", "FORMAT");
-        opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "FORMAT");
+        opts.optopt(
+            "",
+            "rust-profile-generate",
+            "generate PGO profile with rustc build",
+            "PROFILE",
+        );
+        opts.optopt("", "rust-profile-use", "use PGO profile for rustc build", "PROFILE");
+        opts.optflag("", "llvm-profile-generate", "generate PGO profile with llvm built for rustc");
+        opts.optopt("", "llvm-profile-use", "use PGO profile for llvm build", "PROFILE");
 
         // We can't use getopt to parse the options until we have completed specifying which
         // options are valid, but under the current implementation, some options are conditional on
@@ -687,6 +701,8 @@ pub fn parse(args: &[String]) -> Flags {
                 .expect("`color` should be `always`, `never`, or `auto`"),
             rust_profile_use: matches.opt_str("rust-profile-use"),
             rust_profile_generate: matches.opt_str("rust-profile-generate"),
+            llvm_profile_use: matches.opt_str("llvm-profile-use"),
+            llvm_profile_generate: matches.opt_present("llvm-profile-generate"),
         }
     }
 }
index d1397394be75f4455864fc2cbcc18f4eeea7b1e7..0e306cb7211b5e9a186ed0b4d3871572469ba9c2 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::env;
 use std::env::consts::EXE_EXTENSION;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fs::{self, File};
 use std::io;
 use std::path::{Path, PathBuf};
@@ -189,6 +189,19 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
             .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
             .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
 
+        // Parts of our test suite rely on the `FileCheck` tool, which is built by default in
+        // `build/$TARGET/llvm/build/bin` is but *not* then installed to `build/$TARGET/llvm/bin`.
+        // This flag makes sure `FileCheck` is copied in the final binaries directory.
+        cfg.define("LLVM_INSTALL_UTILS", "ON");
+
+        if builder.config.llvm_profile_generate {
+            cfg.define("LLVM_BUILD_INSTRUMENTED", "IR");
+            cfg.define("LLVM_BUILD_RUNTIME", "No");
+        }
+        if let Some(path) = builder.config.llvm_profile_use.as_ref() {
+            cfg.define("LLVM_PROFDATA_FILE", &path);
+        }
+
         if target != "aarch64-apple-darwin" && !target.contains("windows") {
             cfg.define("LLVM_ENABLE_ZLIB", "ON");
         } else {
@@ -831,6 +844,8 @@ fn supported_sanitizers(
         "x86_64-unknown-netbsd" => {
             common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"])
         }
+        "x86_64-unknown-illumos" => common_libs("illumos", "x86_64", &["asan"]),
+        "x86_64-pc-solaris" => common_libs("solaris", "x86_64", &["asan"]),
         "x86_64-unknown-linux-gnu" => {
             common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
         }
@@ -944,3 +959,154 @@ fn run(self, builder: &Builder<'_>) -> Self::Output {
         out_dir
     }
 }
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Libunwind {
+    pub target: TargetSelection,
+}
+
+impl Step for Libunwind {
+    type Output = PathBuf;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/llvm-project/libunwind")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Libunwind { target: run.target });
+    }
+
+    /// Build linunwind.a
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        if builder.config.dry_run {
+            return PathBuf::new();
+        }
+
+        let out_dir = builder.native_dir(self.target).join("libunwind");
+        let root = builder.src.join("src/llvm-project/libunwind");
+
+        if up_to_date(&root, &out_dir.join("libunwind.a")) {
+            return out_dir;
+        }
+
+        builder.info(&format!("Building libunwind.a for {}", self.target.triple));
+        t!(fs::create_dir_all(&out_dir));
+
+        let mut cc_cfg = cc::Build::new();
+        let mut cpp_cfg = cc::Build::new();
+
+        cpp_cfg.cpp(true);
+        cpp_cfg.cpp_set_stdlib(None);
+        cpp_cfg.flag("-nostdinc++");
+        cpp_cfg.flag("-fno-exceptions");
+        cpp_cfg.flag("-fno-rtti");
+        cpp_cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
+
+        for cfg in [&mut cc_cfg, &mut cpp_cfg].iter_mut() {
+            if let Some(ar) = builder.ar(self.target) {
+                cfg.archiver(ar);
+            }
+            cfg.target(&self.target.triple);
+            cfg.host(&builder.config.build.triple);
+            cfg.warnings(false);
+            cfg.debug(false);
+            // get_compiler() need set opt_level first.
+            cfg.opt_level(3);
+            cfg.flag("-fstrict-aliasing");
+            cfg.flag("-funwind-tables");
+            cfg.flag("-fvisibility=hidden");
+            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
+            cfg.include(root.join("include"));
+            cfg.cargo_metadata(false);
+            cfg.out_dir(&out_dir);
+
+            if self.target.contains("x86_64-fortanix-unknown-sgx") {
+                cfg.static_flag(true);
+                cfg.flag("-fno-stack-protector");
+                cfg.flag("-ffreestanding");
+                cfg.flag("-fexceptions");
+
+                // easiest way to undefine since no API available in cc::Build to undefine
+                cfg.flag("-U_FORTIFY_SOURCE");
+                cfg.define("_FORTIFY_SOURCE", "0");
+                cfg.define("RUST_SGX", "1");
+                cfg.define("__NO_STRING_INLINES", None);
+                cfg.define("__NO_MATH_INLINES", None);
+                cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
+                cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
+                cfg.define("NDEBUG", None);
+            }
+        }
+
+        cc_cfg.compiler(builder.cc(self.target));
+        if let Ok(cxx) = builder.cxx(self.target) {
+            cpp_cfg.compiler(cxx);
+        } else {
+            cc_cfg.compiler(builder.cc(self.target));
+        }
+
+        // Don't set this for clang
+        // By default, Clang builds C code in GNU C17 mode.
+        // By default, Clang builds C++ code according to the C++98 standard,
+        // with many C++11 features accepted as extensions.
+        if cc_cfg.get_compiler().is_like_gnu() {
+            cc_cfg.flag("-std=c99");
+        }
+        if cpp_cfg.get_compiler().is_like_gnu() {
+            cpp_cfg.flag("-std=c++11");
+        }
+
+        if self.target.contains("x86_64-fortanix-unknown-sgx") || self.target.contains("musl") {
+            // use the same GCC C compiler command to compile C++ code so we do not need to setup the
+            // C++ compiler env variables on the builders.
+            // Don't set this for clang++, as clang++ is able to compile this without libc++.
+            if cpp_cfg.get_compiler().is_like_gnu() {
+                cpp_cfg.cpp(false);
+                cpp_cfg.compiler(builder.cc(self.target));
+            }
+        }
+
+        let mut c_sources = vec![
+            "Unwind-sjlj.c",
+            "UnwindLevel1-gcc-ext.c",
+            "UnwindLevel1.c",
+            "UnwindRegistersRestore.S",
+            "UnwindRegistersSave.S",
+        ];
+
+        let cpp_sources = vec!["Unwind-EHABI.cpp", "Unwind-seh.cpp", "libunwind.cpp"];
+        let cpp_len = cpp_sources.len();
+
+        if self.target.contains("x86_64-fortanix-unknown-sgx") {
+            c_sources.push("UnwindRustSgx.c");
+        }
+
+        for src in c_sources {
+            cc_cfg.file(root.join("src").join(src).canonicalize().unwrap());
+        }
+
+        for src in &cpp_sources {
+            cpp_cfg.file(root.join("src").join(src).canonicalize().unwrap());
+        }
+
+        cpp_cfg.compile("unwind-cpp");
+
+        // FIXME: https://github.com/alexcrichton/cc-rs/issues/545#issuecomment-679242845
+        let mut count = 0;
+        for entry in fs::read_dir(&out_dir).unwrap() {
+            let file = entry.unwrap().path().canonicalize().unwrap();
+            if file.is_file() && file.extension() == Some(OsStr::new("o")) {
+                // file name starts with "Unwind-EHABI", "Unwind-seh" or "libunwind"
+                let file_name = file.file_name().unwrap().to_str().expect("UTF-8 file name");
+                if cpp_sources.iter().any(|f| file_name.starts_with(&f[..f.len() - 4])) {
+                    cc_cfg.object(&file);
+                    count += 1;
+                }
+            }
+        }
+        assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);
+
+        cc_cfg.compile("unwind");
+        out_dir
+    }
+}
index 8242e091cd4c7890999140b6762762cb81f40cff..e29d990f0f974e1c0d92bcf00f286eb4162d8b45 100644 (file)
@@ -82,6 +82,12 @@ COPY host-x86_64/dist-x86_64-linux/build-clang.sh /tmp/
 RUN ./build-clang.sh
 ENV CC=clang CXX=clang++
 
+ENV PERF_COMMIT 1e19fc4c6168d2f7596e512f42f358f245d8f09d
+RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
+    unzip perf.zip && \
+    mv rustc-perf-$PERF_COMMIT rustc-perf && \
+    rm perf.zip
+
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
index 40a637616d35f1fe434bac93a88a19f3a68b382a..ed5edfec4e1a6c303b2b7a044db8a1db3bc032c0 100755 (executable)
@@ -20,14 +20,18 @@ cd clang-build
 # include path, /rustroot/include, to clang's default include path.
 INC="/rustroot/include:/usr/include"
 
+# We need compiler-rt for the profile runtime (used later to PGO the LLVM build)
+# but sanitizers aren't currently building. Since we don't need those, just
+# disable them.
 hide_output \
     cmake ../llvm \
       -DCMAKE_C_COMPILER=/rustroot/bin/gcc \
       -DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \
       -DCMAKE_BUILD_TYPE=Release \
       -DCMAKE_INSTALL_PREFIX=/rustroot \
+      -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
       -DLLVM_TARGETS_TO_BUILD=X86 \
-      -DLLVM_ENABLE_PROJECTS="clang;lld" \
+      -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \
       -DC_INCLUDE_DIRS="$INC"
 
 hide_output make -j$(nproc)
index 292b3c1d5627a5dc69eeb36025fcec5a7dd356eb..6c713e1f8611faa1017447bc6f2dd97a78cd5942 100644 (file)
@@ -1,12 +1,15 @@
 #!/bin/sh
+
+# ignore-tidy-linelength
+
 set -ex
 
 case "$(uname -m)" in
     x86_64)
-        url="https://ci-mirrors.rust-lang.org/rustc/2018-04-02-sccache-x86_64-unknown-linux-musl"
+        url="https://ci-mirrors.rust-lang.org/rustc/2021-08-24-sccache-v0.2.15-x86_64-unknown-linux-musl"
         ;;
     aarch64)
-        url="https://ci-mirrors.rust-lang.org/rustc/2019-12-17-sccache-aarch64-unknown-linux-gnu"
+        url="https://ci-mirrors.rust-lang.org/rustc/2021-08-25-sccache-v0.2.15-aarch64-unknown-linux-musl"
         ;;
     *)
         echo "unsupported architecture: $(uname -m)"
index aa009a4eac6af877e4e4dc005a2fd9abd19d2f2b..e35e3e670cc64c0b23c4d936e3eef1bab0977098 100755 (executable)
@@ -5,61 +5,59 @@ set -euxo pipefail
 rm -rf /tmp/rustc-pgo
 
 python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
-    --stage 2 library/std --rust-profile-generate=/tmp/rustc-pgo
+    --stage 2 library/std \
+    --rust-profile-generate=/tmp/rustc-pgo \
+    --llvm-profile-generate
 
+# Profile libcore compilation in opt-level=0 and opt-level=3
 RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
     --crate-type=lib ../library/core/src/lib.rs
-
-# Download and build a single-file stress test benchmark on perf.rust-lang.org.
-function pgo_perf_benchmark {
-    local PERF=1e19fc4c6168d2f7596e512f42f358f245d8f09d
-    local github_prefix=https://raw.githubusercontent.com/rust-lang/rustc-perf/$PERF
-    local name=$1
-    local edition=$2
-    curl -o /tmp/$name.rs $github_prefix/collector/benchmarks/$name/src/lib.rs
-
-    RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=$edition \
-        --crate-type=lib /tmp/$name.rs
-}
-
-pgo_perf_benchmark externs 2018
-pgo_perf_benchmark ctfe-stress-4 2018
-pgo_perf_benchmark inflate 2015
-
-cp -pri ../src/tools/cargo /tmp/cargo
-
-# The Cargo repository does not have a Cargo.lock in it, as it relies on the
-# lockfile already present in the rust-lang/rust monorepo. This decision breaks
-# down when Cargo is built outside the monorepo though (like in this case),
-# resulting in a build without any dependency locking.
-#
-# To ensure Cargo is built with locked dependencies even during PGO profiling
-# the following command copies the monorepo's lockfile into the Cargo temporary
-# directory. Cargo will *not* keep that lockfile intact, as it will remove all
-# the dependencies Cargo itself doesn't rely on. Still, it will prevent
-# building Cargo with arbitrary dependency versions.
-#
-# See #81378 for the bug that prompted adding this.
-cp -p ../Cargo.lock /tmp/cargo
-
-# Build cargo (with some flags)
-function pgo_cargo {
-    RUSTC=./build/$PGO_HOST/stage2/bin/rustc \
-        ./build/$PGO_HOST/stage0/bin/cargo $@ \
-        --manifest-path /tmp/cargo/Cargo.toml
-}
-
-# Build a couple different variants of Cargo
-CARGO_INCREMENTAL=1 pgo_cargo check
-echo 'pub fn barbarbar() {}' >> /tmp/cargo/src/cargo/lib.rs
-CARGO_INCREMENTAL=1 pgo_cargo check
-touch /tmp/cargo/src/cargo/lib.rs
-CARGO_INCREMENTAL=1 pgo_cargo check
-pgo_cargo build --release
+RUSTC_BOOTSTRAP=1 ./build/$PGO_HOST/stage2/bin/rustc --edition=2018 \
+    --crate-type=lib -Copt-level=3 ../library/core/src/lib.rs
+
+cp -r /tmp/rustc-perf ./
+chown -R $(whoami): ./rustc-perf
+cd rustc-perf
+
+# Build the collector ahead of time, which is needed to make sure the rustc-fake
+# binary used by the collector is present.
+RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \
+RUSTC_BOOTSTRAP=1 \
+/checkout/obj/build/$PGO_HOST/stage0/bin/cargo build -p collector
+
+# benchmark using profile_local with eprintln, which essentially just means
+# don't actually benchmark -- just make sure we run rustc a bunch of times.
+RUST_LOG=collector=debug \
+RUSTC=/checkout/obj/build/$PGO_HOST/stage0/bin/rustc \
+RUSTC_BOOTSTRAP=1 \
+/checkout/obj/build/$PGO_HOST/stage0/bin/cargo run -p collector --bin collector -- \
+        profile_local \
+        eprintln \
+        /checkout/obj/build/$PGO_HOST/stage2/bin/rustc \
+        Test \
+        --builds Check,Debug,Opt \
+        --cargo /checkout/obj/build/$PGO_HOST/stage0/bin/cargo \
+        --runs All \
+        --include externs,ctfe-stress-4,inflate,cargo,token-stream-stress,match-stress-enum
+
+cd /checkout/obj
 
 # Merge the profile data we gathered
 ./build/$PGO_HOST/llvm/bin/llvm-profdata \
     merge -o /tmp/rustc-pgo.profdata /tmp/rustc-pgo
 
+# Merge the profile data we gathered for LLVM
+# Note that this uses the profdata from the clang we used to build LLVM,
+# which likely has a different version than our in-tree clang.
+/rustroot/bin/llvm-profdata \
+    merge -o /tmp/llvm-pgo.profdata ./build/$PGO_HOST/llvm/build/profiles
+
+# Rustbuild currently doesn't support rebuilding LLVM when PGO options
+# change (or any other llvm-related options); so just clear out the relevant
+# directories ourselves.
+rm -r ./build/$PGO_HOST/llvm ./build/$PGO_HOST/lld
+
 # This produces the actual final set of artifacts.
-$@ --rust-profile-use=/tmp/rustc-pgo.profdata
+$@ \
+    --rust-profile-use=/tmp/rustc-pgo.profdata \
+    --llvm-profile-use=/tmp/llvm-pgo.profdata
index d3c298992254ef3424da236fbbaafceef4fb8e20..e143152f330cf3f2931f18b41d22c3ddad5afd83 100755 (executable)
@@ -8,7 +8,7 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 if isMacOS; then
-    curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2018-04-02-sccache-x86_64-apple-darwin"
+    curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2021-08-25-sccache-v0.2.15-x86_64-apple-darwin"
     chmod +x /usr/local/bin/sccache
 elif isWindows; then
     mkdir -p sccache
index 7e49659102f0977d9142190e1ba23345c0f00eb1..fcb5e0ea68112d85a1d29a7a7335978ef2a02181 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7e49659102f0977d9142190e1ba23345c0f00eb1
+Subproject commit fcb5e0ea68112d85a1d29a7a7335978ef2a02181
index 3710b0cae783d0bcd2b42452a63b081473f5970a..2d9b1b9da706de24650fdc5c3b0182f55c82115d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3710b0cae783d0bcd2b42452a63b081473f5970a
+Subproject commit 2d9b1b9da706de24650fdc5c3b0182f55c82115d
index 4f9fcaa30d11ba52b641e6fd5206536d65838af9..c3a51e23859554369e6bbb5128dcef0e4f159fb5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4f9fcaa30d11ba52b641e6fd5206536d65838af9
+Subproject commit c3a51e23859554369e6bbb5128dcef0e4f159fb5
index 0c7e5bd1428e7838252bb57b7f0fbfda4ec82f02..fe6227eb3c8533200c52dffa42ef1b6f2f02c40e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0c7e5bd1428e7838252bb57b7f0fbfda4ec82f02
+Subproject commit fe6227eb3c8533200c52dffa42ef1b6f2f02c40e
index 4884fe45c14f8b22121760fb117181bb4da8dfe0..0e5ed7a4bec065f0cc18c35d1c904639e095314d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4884fe45c14f8b22121760fb117181bb4da8dfe0
+Subproject commit 0e5ed7a4bec065f0cc18c35d1c904639e095314d
index 0dc9cd4e89f00cb5230f120e1a083916386e422b..04f489c889235fe3b6dfe678ae5410d07deda958 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0dc9cd4e89f00cb5230f120e1a083916386e422b
+Subproject commit 04f489c889235fe3b6dfe678ae5410d07deda958
index c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f..95f1acf9a39d6f402f654e917e2c1dfdb779c5fc 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f
+Subproject commit 95f1acf9a39d6f402f654e917e2c1dfdb779c5fc
index 7d3cad7988c8c717780565a5aa776784201cf5d8..7f482f0f2b1a084fd0c1501a4dac6f8906ffcb35 100644 (file)
@@ -93,7 +93,7 @@ This informs `rustc` of the name of your crate.
 <a id="option-edition"></a>
 ## `--edition`: specify the edition to use
 
-This flag takes a value of `2015` or `2018`. The default is `2015`. More
+This flag takes a value of `2015`, `2018` or `2021`. The default is `2015`. More
 information about editions may be found in the [edition guide].
 
 [edition guide]: ../edition-guide/introduction.html
index 3e616f226ed76f908ecc8d291e4afeddfcbf0f4b..7bd46fafadf8344fe432971136857780cb639df4 100644 (file)
@@ -1,11 +1,12 @@
 # Lint levels
 
-In `rustc`, lints are divided into four *levels*:
+In `rustc`, lints are divided into five *levels*:
 
 1. allow
 2. warn
-3. deny
-4. forbid
+3. force-warn
+4. deny
+5. forbid
 
 Each lint has a default level (explained in the lint listing later in this
 chapter), and the compiler has a default warning level. First, let's explain
@@ -57,6 +58,14 @@ warning: unused variable: `x`
   = note: to avoid this warning, consider using `_x` instead
 ```
 
+## force-warn
+
+'force-warn' is a special lint level. It's the same as 'warn' in that a lint
+at this level will produce a warning, but unlike the 'warn' level, the
+'force-warn' level cannot be overridden. If a lint is set to 'force-warn', it
+is guaranteed to warn: no more, no less. This is true even if the overall lint
+level is capped via cap-lints.
+
 ## deny
 
 A 'deny' lint produces an error if you violate it. For example, this code
@@ -87,11 +96,12 @@ This lint level gives you that.
 
 ## forbid
 
-'forbid' is a special lint level that's stronger than 'deny'. It's the same
-as 'deny' in that a lint at this level will produce an error, but unlike the
-'deny' level, the 'forbid' level can not be overridden to be anything lower
-than an error.  However, lint levels may still be capped with `--cap-lints`
-(see below) so `rustc --cap-lints warn` will make lints set to 'forbid' just
+'forbid' is a special lint level that fills the same role for 'deny' that
+'force-warn' does for 'warn'. It's the same as 'deny' in that a lint at this
+level will produce an error, but unlike the 'deny' level, the 'forbid' level
+can not be overridden to be anything lower than an error.  However, lint
+levels may still be capped with `--cap-lints` (see below) so `rustc --cap-
+lints warn` will make lints set to 'forbid' just
 warn.
 
 ## Configuring warning levels
@@ -113,8 +123,8 @@ certain lint levels. We'll talk about that last.
 
 ### Via compiler flag
 
-The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints
-into allowed, warning, deny, or forbid levels, like this:
+The `-A`, `-W`, `--force-warn` `-D`, and `-F` flags let you turn one or more lints
+into allowed, warning, force-warn, deny, or forbid levels, like this:
 
 ```bash
 $ rustc lib.rs --crate-type=lib -W missing-docs
@@ -158,7 +168,7 @@ You can also pass each flag more than once for changing multiple lints:
 $ rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables
 ```
 
-And of course, you can mix these four flags together:
+And of course, you can mix these five flags together:
 
 ```bash
 $ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables
@@ -176,6 +186,10 @@ You can make use of this behavior by overriding the level of one specific lint o
 $ rustc lib.rs --crate-type=lib -D unused -A unused-variables
 ```
 
+Since `force-warn` and `forbid` cannot be overridden, setting
+one of them will prevent any later level for the same lint from
+taking effect.
+
 ### Via an attribute
 
 You can also modify the lint level with a crate-wide attribute:
@@ -207,7 +221,8 @@ warning: missing documentation for a function
   | ^^^^^^^^^^^^
 ```
 
-All four, `warn`, `allow`, `deny`, and `forbid` all work this way.
+`warn`, `allow`, `deny`, and `forbid` all work this way. There is
+no way to set a lint to `force-warn` using an attribute.
 
 You can also pass in multiple lints per attribute:
 
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warn.md b/src/doc/unstable-book/src/compiler-flags/force-warn.md
deleted file mode 100644 (file)
index 052de0f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# `force-warn`
-
-The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
-
-------------------------
-
-This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warn` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
-
-## Example
-
-```rust,ignore (partial-example)
-#![allow(dead_code)]
-
-fn dead_function() {}
-// This would normally not produce a warning even though the
-// function is not used, because dead code is being allowed
-
-fn main() {}
-```
-
-We can force a warning to be produced by providing `--force-warn dead_code` to rustc.
index 220b74ca6e6e1b438c26383fc3ce0ac9b33c50b7..a10928a7471770ae520ba86dd2a8396096cce420 100644 (file)
@@ -31,6 +31,7 @@ Inline assembly is currently supported on the following architectures:
 - MIPS32r2 and MIPS64r2
 - wasm32
 - BPF
+- SPIR-V
 
 ## Basic usage
 
@@ -188,8 +189,7 @@ As you can see, this assembly fragment will still work correctly if `a` and `b`
 
 Some instructions require that the operands be in a specific register.
 Therefore, Rust inline assembly provides some more specific constraint specifiers.
-While `reg` is generally available on any architecture, these are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi`
-among others can be addressed by their name.
+While `reg` is generally available on any architecture, explicit registers are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi` among others can be addressed by their name.
 
 ```rust,allow_fail,no_run
 #![feature(asm)]
@@ -199,11 +199,9 @@ unsafe {
 }
 ```
 
-In this example we call the `out` instruction to output the content of the `cmd` variable
-to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand
-we had to use the `eax` constraint specifier.
+In this example we call the `out` instruction to output the content of the `cmd` variable to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand we had to use the `eax` constraint specifier.
 
-Note that unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.
+> **Note**: unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.
 
 Consider this example which uses the x86 `mul` instruction:
 
@@ -237,11 +235,9 @@ The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.
 ## Clobbered registers
 
 In many cases inline assembly will modify state that is not needed as an output.
-Usually this is either because we have to use a scratch register in the assembly,
-or instructions modify state that we don't need to further examine.
+Usually this is either because we have to use a scratch register in the assembly or because instructions modify state that we don't need to further examine.
 This state is generally referred to as being "clobbered".
-We need to tell the compiler about this since it may need to save and restore this state
-around the inline assembly block.
+We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
 
 ```rust,allow_fail
 #![feature(asm)]
@@ -321,8 +317,7 @@ fn call_foo(arg: i32) -> i32 {
 }
 ```
 
-Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`:
-the compiler will automatically insert the appropriate mangled symbol name into the assembly code.
+Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`: the compiler will automatically insert the appropriate mangled symbol name into the assembly code.
 
 By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered.
 
@@ -355,9 +350,8 @@ If you use a smaller data type (e.g. `u16`) with an operand and forget the use t
 ## Memory address operands
 
 Sometimes assembly instructions require operands passed via memory addresses/memory locations.
-You have to manually use the memory address syntax specified by the respectively architectures.
-For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/outputs in `[]`
-to indicate they are memory operands:
+You have to manually use the memory address syntax specified by the target architecture.
+For example, on x86/x86_64 using intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands:
 
 ```rust,allow_fail
 #![feature(asm, llvm_asm)]
@@ -373,9 +367,15 @@ unsafe {
 
 ## Labels
 
-The compiler is allowed to instantiate multiple copies an `asm!` block, for example when the function containing it is inlined in multiple places. As a consequence, you should only use GNU assembler [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
+Any reuse of a named label, local or otherwise, can result in a assembler or linker error or may cause other strange behavior. Reuse of a named label can happen in a variety of ways including:
 
-Moreover, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values.
+-   explicitly: using a label more than once in one `asm!` block, or multiple times across blocks
+-   implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places.
+-   implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels
+
+As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
+
+Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `option(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
 
 ```rust,allow_fail
 #![feature(asm)]
@@ -410,7 +410,7 @@ Second, that when a numeric label is used as a reference (as an instruction oper
 
 ## Options
 
-By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
+By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However, in many cases it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
 
 Let's take our previous example of an `add` instruction:
 
@@ -470,6 +470,7 @@ Inline assembly is currently supported on the following architectures:
 - MIPS32r2 and MIPS64r2
 - wasm32
 - BPF
+- SPIR-V
 
 Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
 
@@ -584,6 +585,8 @@ Here is the list of currently supported register classes:
 | PowerPC | `reg` | `r[0-31]` | `r` |
 | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
 | PowerPC | `freg` | `f[0-31]` | `f` |
+| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
+| PowerPC | `xer` | `xer` | Only clobbers |
 | wasm32 | `local` | None\* | `r` |
 | BPF | `reg` | `r[0-10]` | `r` |
 | BPF | `wreg` | `w[0-10]` | `w` |
@@ -637,6 +640,8 @@ Each register class has constraints on which value types they can be used with.
 | PowerPC | `reg` | None | `i8`, `i16`, `i32` |
 | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
 | PowerPC | `freg` | None | `f32`, `f64` |
+| PowerPC | `cr` | N/A | Only clobbers |
+| PowerPC | `xer` | N/A | Only clobbers |
 | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
 | BPF | `reg` | None | `i8` `i16` `i32` `i64` |
 | BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
@@ -836,7 +841,7 @@ The compiler performs some additional checks on options:
   - Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. Code should not rely on this however since it depends on the results of register allocation.
 - Behavior is undefined if execution unwinds out of an asm block.
   - This also applies if the assembly code calls a function which then unwinds.
-- The set of memory locations that assembly code is allowed the read and write are the same as those allowed for an FFI function.
+- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
   - Refer to the unsafe code guidelines for the exact rules.
   - If the `readonly` option is set, then only memory reads are allowed.
   - If the `nomem` option is set then no reads or writes to memory are allowed.
index 8ad09a9edc01cb3e28712c2cbdb4c119056e7aac..11adb56490b32406e54f218cfe30b53aad27344f 100644 (file)
@@ -331,9 +331,10 @@ fn extract_for_generics(&self, pred: ty::Predicate<'tcx>) -> FxHashSet<GenericPa
                 match br {
                     // We only care about named late bound regions, as we need to add them
                     // to the 'for<>' section
-                    ty::BrNamed(_, name) => {
-                        Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
-                    }
+                    ty::BrNamed(_, name) => Some(GenericParamDef {
+                        name,
+                        kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+                    }),
                     _ => None,
                 }
             })
@@ -351,7 +352,7 @@ fn make_final_bounds(
             .flat_map(|(ty, mut bounds)| {
                 if let Some(data) = ty_to_fn.get(&ty) {
                     let (poly_trait, output) =
-                        (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
+                        (data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
                     let new_ty = match poly_trait.trait_ {
                         Type::ResolvedPath { ref path, ref did, ref is_generic } => {
                             let mut new_path = path.clone();
@@ -659,7 +660,7 @@ fn param_env_to_generics(
                         bounds.insert(0, GenericBound::maybe_sized(self.cx));
                     }
                 }
-                GenericParamDefKind::Lifetime => {}
+                GenericParamDefKind::Lifetime { .. } => {}
                 GenericParamDefKind::Const { ref mut default, .. } => {
                     // We never want something like `impl<const N: usize = 10>`
                     default.take();
index fa29b54264948c3554531e3473fa5f5baa442ccd..0c81a5584301355e4d70e84c4b8139751c0d5b6b 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
-use rustc_metadata::creader::LoadedMacro;
+use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
     let fqn = if let ItemType::Macro = kind {
         // Check to see if it is a macro 2.0 or built-in macro
         if matches!(
-            cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())),
+            CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.sess()),
             LoadedMacro::MacroDef(def, _)
                 if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
                     if !ast_def.macro_rules)
@@ -558,7 +558,7 @@ fn build_macro(
     import_def_id: Option<DefId>,
 ) -> clean::ItemKind {
     let imported_from = cx.tcx.crate_name(def_id.krate);
-    match cx.enter_resolver(|r| r.cstore().load_macro_untracked(def_id, cx.sess())) {
+    match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) {
         LoadedMacro::MacroDef(item_def, _) => {
             if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
                 clean::MacroItem(clean::Macro {
index b6ff3890c584edf4268078af879d13d6d75627d7..71348b3eb65ff022d53f4d6b9c82d2f3da9f53ef 100644 (file)
@@ -30,6 +30,7 @@
 use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_typeck::hir_ty_to_ty;
 
+use std::assert_matches::assert_matches;
 use std::collections::hash_map::Entry;
 use std::default::Default;
 use std::hash::Hash;
@@ -91,7 +92,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
         items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
-        items.extend(self.macros.iter().map(|x| x.clean(cx)));
 
         // determine if we should display the inner contents or
         // the outer `mod` item for the source code.
@@ -200,9 +200,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
             .collect_referenced_late_bound_regions(&poly_trait_ref)
             .into_iter()
             .filter_map(|br| match br {
-                ty::BrNamed(_, name) => {
-                    Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
-                }
+                ty::BrNamed(_, name) => Some(GenericParamDef {
+                    name,
+                    kind: GenericParamDefKind::Lifetime { outlives: vec![] },
+                }),
                 _ => None,
             })
             .collect();
@@ -242,30 +243,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
     }
 }
 
-impl Clean<Lifetime> for hir::GenericParam<'_> {
-    fn clean(&self, _: &mut DocContext<'_>) -> Lifetime {
-        match self.kind {
-            hir::GenericParamKind::Lifetime { .. } => {
-                if !self.bounds.is_empty() {
-                    let mut bounds = self.bounds.iter().map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => lt,
-                        _ => panic!(),
-                    });
-                    let name = bounds.next().expect("no more bounds").name.ident();
-                    let mut s = format!("{}: {}", self.name.ident(), name);
-                    for bound in bounds {
-                        s.push_str(&format!(" + {}", bound.name.ident()));
-                    }
-                    Lifetime(Symbol::intern(&s))
-                } else {
-                    Lifetime(self.name.ident().name)
-                }
-            }
-            _ => panic!(),
-        }
-    }
-}
-
 impl Clean<Constant> for hir::ConstArg {
     fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
         Constant {
@@ -303,11 +280,30 @@ fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
 impl Clean<WherePredicate> for hir::WherePredicate<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
         match *self {
-            hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
-                ty: wbp.bounded_ty.clean(cx),
-                bounds: wbp.bounds.clean(cx),
-                bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
-            },
+            hir::WherePredicate::BoundPredicate(ref wbp) => {
+                let bound_params = wbp
+                    .bound_generic_params
+                    .into_iter()
+                    .map(|param| {
+                        // Higher-ranked params must be lifetimes.
+                        // Higher-ranked lifetimes can't have bounds.
+                        assert_matches!(
+                            param,
+                            hir::GenericParam {
+                                kind: hir::GenericParamKind::Lifetime { .. },
+                                bounds: [],
+                                ..
+                            }
+                        );
+                        Lifetime(param.name.ident().name)
+                    })
+                    .collect();
+                WherePredicate::BoundPredicate {
+                    ty: wbp.bounded_ty.clean(cx),
+                    bounds: wbp.bounds.clean(cx),
+                    bound_params,
+                }
+            }
 
             hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
                 lifetime: wrp.lifetime.clean(cx),
@@ -413,7 +409,9 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
 impl Clean<GenericParamDef> for ty::GenericParamDef {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
-            ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
+            ty::GenericParamDefKind::Lifetime => {
+                (self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
+            }
             ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
                 let default = if has_default {
                     let mut default = cx.tcx.type_of(self.def_id).clean(cx);
@@ -463,21 +461,15 @@ impl Clean<GenericParamDef> for hir::GenericParam<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
         let (name, kind) = match self.kind {
             hir::GenericParamKind::Lifetime { .. } => {
-                let name = if !self.bounds.is_empty() {
-                    let mut bounds = self.bounds.iter().map(|bound| match bound {
-                        hir::GenericBound::Outlives(lt) => lt,
+                let outlives = self
+                    .bounds
+                    .iter()
+                    .map(|bound| match bound {
+                        hir::GenericBound::Outlives(lt) => lt.clean(cx),
                         _ => panic!(),
-                    });
-                    let name = bounds.next().expect("no more bounds").name.ident();
-                    let mut s = format!("{}: {}", self.name.ident(), name);
-                    for bound in bounds {
-                        s.push_str(&format!(" + {}", bound.name.ident()));
-                    }
-                    Symbol::intern(&s)
-                } else {
-                    self.name.ident().name
-                };
-                (name, GenericParamDefKind::Lifetime)
+                    })
+                    .collect();
+                (self.name.ident().name, GenericParamDefKind::Lifetime { outlives })
             }
             hir::GenericParamKind::Type { ref default, synthetic } => (
                 self.name.ident().name,
@@ -537,7 +529,7 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
             .map(|param| {
                 let param: GenericParamDef = param.clean(cx);
                 match param.kind {
-                    GenericParamDefKind::Lifetime => unreachable!(),
+                    GenericParamDefKind::Lifetime { .. } => unreachable!(),
                     GenericParamDefKind::Type { did, ref bounds, .. } => {
                         cx.impl_trait_bounds.insert(did.into(), bounds.clone());
                     }
@@ -570,7 +562,7 @@ fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
                     {
                         for param in &mut generics.params {
                             match param.kind {
-                                GenericParamDefKind::Lifetime => {}
+                                GenericParamDefKind::Lifetime { .. } => {}
                                 GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
                                     if &param.name == name {
                                         mem::swap(bounds, ty_bounds);
@@ -1312,10 +1304,11 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
         }
         hir::QPath::TypeRelative(ref qself, ref segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
-            let res = if let ty::Projection(proj) = ty.kind() {
-                Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
-            } else {
-                Res::Err
+            let res = match ty.kind() {
+                ty::Projection(proj) => Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id),
+                // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
+                ty::Error(_) => return Type::Infer,
+                _ => bug!("clean: expected associated type, found `{:?}`", ty),
             };
             let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
             Type::QPath {
@@ -1380,6 +1373,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                 DynTrait(bounds, lifetime)
             }
             TyKind::BareFn(ref barefn) => BareFunction(Box::new(barefn.clean(cx))),
+            // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
             TyKind::Infer | TyKind::Err => Infer,
             TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
         }
@@ -1703,12 +1697,28 @@ fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct {
     }
 }
 
+impl Clean<Vec<Item>> for hir::VariantData<'_> {
+    fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
+        self.fields().iter().map(|x| x.clean(cx)).collect()
+    }
+}
+
 impl Clean<Item> for ty::VariantDef {
     fn clean(&self, cx: &mut DocContext<'_>) -> Item {
         let kind = match self.ctor_kind {
             CtorKind::Const => Variant::CLike,
             CtorKind::Fn => Variant::Tuple(
-                self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
+                self.fields
+                    .iter()
+                    .map(|field| {
+                        let name = Some(field.ident.name);
+                        let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx));
+                        let what_rustc_thinks =
+                            Item::from_def_id_and_parts(field.did, name, kind, cx);
+                        // don't show `pub` for fields, which are always public
+                        Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
+                    })
+                    .collect(),
             ),
             CtorKind::Fictive => Variant::Struct(VariantStruct {
                 struct_type: CtorKind::Fictive,
@@ -1738,13 +1748,7 @@ impl Clean<Variant> for hir::VariantData<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
         match self {
             hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
-            // Important note here: `Variant::Tuple` is used on tuple structs which are not in an
-            // enum (so where converting from `ty::VariantDef`). In case we are in an enum, the kind
-            // is provided by the `Variant` wrapper directly, and since we need the fields' name
-            // (even for a tuple struct variant!), it's simpler to just store it as a
-            // `Variant::Struct` instead of a `Variant::Tuple` (otherwise it would force us to make
-            // a lot of changes when rendering them to generate the name as well).
-            hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)),
+            hir::VariantData::Tuple(..) => Variant::Tuple(self.clean(cx)),
             hir::VariantData::Unit(..) => Variant::CLike,
         }
     }
@@ -1764,10 +1768,9 @@ impl Clean<GenericArgs> for hir::GenericArgs<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
         if self.parenthesized {
             let output = self.bindings[0].ty().clean(cx);
-            GenericArgs::Parenthesized {
-                inputs: self.inputs().clean(cx),
-                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
-            }
+            let output =
+                if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
+            GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output }
         } else {
             GenericArgs::AngleBracketed {
                 args: self
@@ -1779,7 +1782,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
                         }
                         hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
                         hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
-                        hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
+                        hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
                         hir::GenericArg::Infer(_inf) => GenericArg::Infer,
                     })
                     .collect(),
@@ -1861,6 +1864,10 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                 ItemKind::Fn(ref sig, ref generics, body_id) => {
                     clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
                 }
+                ItemKind::Macro(ref macro_def) => MacroItem(Macro {
+                    source: display_macro_source(cx, name, &macro_def, def_id, &item.vis),
+                    imported_from: None,
+                }),
                 ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
                     let items = item_ids
                         .iter()
@@ -2138,24 +2145,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
     }
 }
 
-impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
-    fn clean(&self, cx: &mut DocContext<'_>) -> Item {
-        let (item, renamed) = self;
-        let name = renamed.unwrap_or(item.ident.name);
-        let def_id = item.def_id.to_def_id();
-
-        Item::from_hir_id_and_parts(
-            item.hir_id(),
-            Some(name),
-            MacroItem(Macro {
-                source: display_macro_source(cx, name, &item.ast, def_id, &item.vis),
-                imported_from: None,
-            }),
-            cx,
-        )
-    }
-}
-
 impl Clean<TypeBinding> for hir::TypeBinding<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
         TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
index c0d52d349280f09b538503150e89e078c59d9d85..d139b19f5dc43f3961969b636066e3b4acab1085 100644 (file)
                 });
             }
             PP::Parenthesized { ref mut output, .. } => match output {
-                Some(o) => assert_eq!(o, rhs),
+                Some(o) => assert_eq!(o.as_ref(), rhs),
                 None => {
                     if *rhs != clean::Type::Tuple(Vec::new()) {
-                        *output = Some(rhs.clone());
+                        *output = Some(Box::new(rhs.clone()));
                     }
                 }
             },
index 702557491433111dd7ddf830155a6fc2ae9d10a9..5eff56a2200e10d396cfc9eba35c29b37b486859 100644 (file)
@@ -715,6 +715,7 @@ impl ItemKind {
             StructItem(s) => s.fields.iter(),
             UnionItem(u) => u.fields.iter(),
             VariantItem(Variant::Struct(v)) => v.fields.iter(),
+            VariantItem(Variant::Tuple(v)) => v.iter(),
             EnumItem(e) => e.variants.iter(),
             TraitItem(t) => t.items.iter(),
             ImplItem(i) => i.items.iter(),
@@ -1230,7 +1231,9 @@ impl WherePredicate {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericParamDefKind {
-    Lifetime,
+    Lifetime {
+        outlives: Vec<Lifetime>,
+    },
     Type {
         did: DefId,
         bounds: Vec<GenericBound>,
@@ -1256,7 +1259,7 @@ impl GenericParamDefKind {
         match self {
             GenericParamDefKind::Type { default, .. } => default.clone(),
             GenericParamDefKind::Const { ty, .. } => Some(ty.clone()),
-            GenericParamDefKind::Lifetime => None,
+            GenericParamDefKind::Lifetime { .. } => None,
         }
     }
 }
@@ -1270,7 +1273,7 @@ impl GenericParamDefKind {
 impl GenericParamDef {
     crate fn is_synthetic_type_param(&self) -> bool {
         match self.kind {
-            GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
+            GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
             GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(),
         }
     }
@@ -1937,7 +1940,7 @@ impl Visibility {
 #[derive(Clone, Debug)]
 crate enum Variant {
     CLike,
-    Tuple(Vec<Type>),
+    Tuple(Vec<Item>),
     Struct(VariantStruct),
 }
 
@@ -2011,22 +2014,37 @@ impl Path {
 crate enum GenericArg {
     Lifetime(Lifetime),
     Type(Type),
-    Const(Constant),
+    Const(Box<Constant>),
     Infer,
 }
 
+// `GenericArg` can occur many times in a single `Path`, so make sure it
+// doesn't increase in size unexpectedly.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericArg, 80);
+
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate enum GenericArgs {
     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
-    Parenthesized { inputs: Vec<Type>, output: Option<Type> },
+    Parenthesized { inputs: Vec<Type>, output: Option<Box<Type>> },
 }
 
+// `GenericArgs` is in every `PathSegment`, so its size can significantly
+// affect rustdoc's memory usage.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(GenericArgs, 56);
+
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 crate struct PathSegment {
     crate name: Symbol,
     crate args: GenericArgs,
 }
 
+// `PathSegment` usually occurs multiple times in every `Path`, so its size can
+// significantly affect rustdoc's memory usage.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(PathSegment, 64);
+
 #[derive(Clone, Debug)]
 crate struct Typedef {
     crate type_: Type,
index bdd5350aab2cb1571f81bf8ed1e8c8bcecf21e9a..de2cd60d2edcd048cca1cc1d4151c7ecea0aba2d 100644 (file)
@@ -121,7 +121,7 @@ fn external_generic_args(
                 ty_kind = Some(ty.kind());
                 Some(GenericArg::Type(ty.clean(cx)))
             }
-            GenericArgKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
+            GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(ct.clean(cx)))),
         })
         .collect();
 
@@ -287,7 +287,7 @@ pub(super) fn external_path(
 
 crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     match n.val {
-        ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
+        ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) => {
             let mut s = if let Some(def) = def.as_local() {
                 let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
                 print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
index eef6985ea30a0ff75d0f22f801cab8bb1c75aa72..97930f106994a3a95df9fe2b1be22d098c0c97f6 100644 (file)
@@ -671,8 +671,7 @@ fn println_condition(condition: Condition) {
             return Err(1);
         }
 
-        let (lint_opts, describe_lints, lint_cap) =
-            get_cmd_lint_options(matches, error_format, &debugging_opts);
+        let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
         Ok(Options {
             input,
index e96eba2f17dbf549f75ce6c8e0962ff43dcc9423..bd1d970fc199b6237515bb90518e28d643f2d748 100644 (file)
@@ -4,9 +4,8 @@
 use rustc_errors::emitter::{Emitter, EmitterWriter};
 use rustc_errors::json::JsonEmitter;
 use rustc_feature::UnstableFeatures;
-use rustc_hir::def::Namespace::TypeNS;
 use rustc_hir::def::Res;
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::HirId;
 use rustc_hir::{
     intravisit::{self, NestedVisitorMap, Visitor},
@@ -23,7 +22,7 @@
 use rustc_session::Session;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 
 use std::cell::RefCell;
 use std::mem;
@@ -301,41 +300,13 @@ impl<'tcx> DocContext<'tcx> {
 }
 
 crate fn create_resolver<'a>(
-    externs: config::Externs,
     queries: &Queries<'a>,
     sess: &Session,
 ) -> Rc<RefCell<interface::BoxedResolver>> {
-    let extern_names: Vec<String> = externs
-        .iter()
-        .filter(|(_, entry)| entry.add_prelude)
-        .map(|(name, _)| name)
-        .cloned()
-        .collect();
-
-    let (_, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
-
-    // Before we actually clone it, let's force all the extern'd crates to
-    // actually be loaded, just in case they're only referred to inside
-    // intra-doc links
-    resolver.borrow_mut().access(|resolver| {
-        sess.time("load_extern_crates", || {
-            for extern_name in &extern_names {
-                debug!("loading extern crate {}", extern_name);
-                if let Err(()) = resolver
-                    .resolve_str_path_error(
-                        DUMMY_SP,
-                        extern_name,
-                        TypeNS,
-                        LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
-                  ) {
-                    warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
-                  }
-            }
-        });
-    });
+    let (krate, resolver, _) = &*abort_on_err(queries.expansion(), sess).peek();
+    let resolver = resolver.clone();
 
-    // Now we're good to clone the resolver because everything should be loaded
-    resolver.clone()
+    crate::passes::collect_intra_doc_links::load_intra_link_crates(resolver, krate)
 }
 
 crate fn run_global_ctxt(
index 083d82cb414d85fca06758a4618e4144e8fbeb3d..e6097f5cad7f30688168a3107bec371e08891826 100644 (file)
             let mut global_ctxt = queries.global_ctxt()?.take();
 
             let collector = global_ctxt.enter(|tcx| {
-                let krate = tcx.hir().krate();
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
                 let mut opts = scrape_test_config(crate_attrs);
                 hir_collector.visit_testable(
                     "".to_string(),
                     CRATE_HIR_ID,
-                    krate.module().inner,
-                    |this| {
-                        intravisit::walk_crate(this, krate);
-                    },
+                    tcx.hir().span(CRATE_HIR_ID),
+                    |this| tcx.hir().walk_toplevel_module(this),
                 );
 
                 collector
@@ -361,7 +358,7 @@ fn run_test(
     for debugging_option_str in &options.debugging_opts_strs {
         compiler.arg("-Z").arg(&debugging_option_str);
     }
-    if no_run && !compile_fail {
+    if no_run && !compile_fail && options.persist_doctests.is_none() {
         compiler.arg("--emit=metadata");
     }
     compiler.arg("--target").arg(match target {
@@ -1171,10 +1168,21 @@ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item<'_>) {
-        let name = if let hir::ItemKind::Impl(impl_) = &item.kind {
-            rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
-        } else {
-            item.ident.to_string()
+        let name = match &item.kind {
+            hir::ItemKind::Macro(ref macro_def) => {
+                // FIXME(#88038): Non exported macros have historically not been tested,
+                // but we really ought to start testing them.
+                let def_id = item.def_id.to_def_id();
+                if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
+                    intravisit::walk_item(self, item);
+                    return;
+                }
+                item.ident.to_string()
+            }
+            hir::ItemKind::Impl(impl_) => {
+                rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
+            }
+            _ => item.ident.to_string(),
         };
 
         self.visit_testable(name, item.hir_id(), item.span, |this| {
@@ -1216,15 +1224,6 @@ fn visit_field_def(&mut self, f: &'hir hir::FieldDef<'_>) {
             intravisit::walk_field_def(this, f);
         });
     }
-
-    fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) {
-        self.visit_testable(
-            macro_def.ident.to_string(),
-            macro_def.hir_id(),
-            macro_def.span,
-            |_| (),
-        );
-    }
 }
 
 #[cfg(test)]
index eadac89f79ef22e0abcb25e6ae19d3d57cd37d14..8f1e8f277c5fe8795a7a7d8ca98471cf3e8df29c 100644 (file)
@@ -5,6 +5,7 @@
 
 use rustc_hir as hir;
 
+#[derive(Debug)]
 crate struct Module<'hir> {
     crate name: Symbol,
     crate where_inner: Span,
     // (item, renamed)
     crate items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
     crate foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
-    crate macros: Vec<(&'hir hir::MacroDef<'hir>, Option<Symbol>)>,
 }
 
 impl Module<'hir> {
     crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> {
-        Module {
-            name,
-            id,
-            where_inner,
-            mods: Vec::new(),
-            items: Vec::new(),
-            foreigns: Vec::new(),
-            macros: Vec::new(),
-        }
+        Module { name, id, where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new() }
     }
 
     crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span {
index 45aae71d2dc574e97d74200dae541747260458ee..b4859e4c9c7fe2e10340f66df721dc7ef9214e3d 100644 (file)
@@ -56,6 +56,10 @@ fn fold_inner_recur(&mut self, kind: ItemKind) -> ItemKind {
                             || j.fields.iter().any(|f| f.is_stripped());
                         VariantItem(Variant::Struct(j))
                     }
+                    Variant::Tuple(fields) => {
+                        let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+                        VariantItem(Variant::Tuple(fields))
+                    }
                     _ => VariantItem(i2),
                 }
             }
index eb7c12d13c339029bacf8566c62837f88dae3071..ea0458034899c54b2db6ff4368c8b7ba506a1c56 100644 (file)
@@ -155,9 +155,23 @@ impl clean::GenericParamDef {
         &'a self,
         cx: &'a Context<'tcx>,
     ) -> impl fmt::Display + 'a + Captures<'tcx> {
-        display_fn(move |f| match self.kind {
-            clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
-            clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
+        display_fn(move |f| match &self.kind {
+            clean::GenericParamDefKind::Lifetime { outlives } => {
+                write!(f, "{}", self.name)?;
+
+                if !outlives.is_empty() {
+                    f.write_str(": ")?;
+                    for (i, lt) in outlives.iter().enumerate() {
+                        if i != 0 {
+                            f.write_str(" + ")?;
+                        }
+                        write!(f, "{}", lt.print())?;
+                    }
+                }
+
+                Ok(())
+            }
+            clean::GenericParamDefKind::Type { bounds, default, .. } => {
                 f.write_str(&*self.name.as_str())?;
 
                 if !bounds.is_empty() {
@@ -178,7 +192,7 @@ impl clean::GenericParamDef {
 
                 Ok(())
             }
-            clean::GenericParamDefKind::Const { ref ty, ref default, .. } => {
+            clean::GenericParamDefKind::Const { ty, default, .. } => {
                 if f.alternate() {
                     write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
                 } else {
@@ -387,7 +401,7 @@ impl clean::GenericBound {
                 let modifier_str = match modifier {
                     hir::TraitBoundModifier::None => "",
                     hir::TraitBoundModifier::Maybe => "?",
-                    hir::TraitBoundModifier::MaybeConst => "?const",
+                    hir::TraitBoundModifier::MaybeConst => "~const",
                 };
                 if f.alternate() {
                     write!(f, "{}{:#}", modifier_str, ty.print(cx))
diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
new file mode 100644 (file)
index 0000000..bbdc91c
--- /dev/null
@@ -0,0 +1,119 @@
+//! See [`HtmlWithLimit`].
+
+use std::fmt::Write;
+use std::ops::ControlFlow;
+
+use crate::html::escape::Escape;
+
+/// A buffer that allows generating HTML with a length limit.
+///
+/// This buffer ensures that:
+///
+/// * all tags are closed,
+/// * tags are closed in the reverse order of when they were opened (i.e., the correct HTML order),
+/// * no tags are left empty (e.g., `<em></em>`) due to the length limit being reached,
+/// * all text is escaped.
+#[derive(Debug)]
+pub(super) struct HtmlWithLimit {
+    buf: String,
+    len: usize,
+    limit: usize,
+    /// A list of tags that have been requested to be opened via [`Self::open_tag()`]
+    /// but have not actually been pushed to `buf` yet. This ensures that tags are not
+    /// left empty (e.g., `<em></em>`) due to the length limit being reached.
+    queued_tags: Vec<&'static str>,
+    /// A list of all tags that have been opened but not yet closed.
+    unclosed_tags: Vec<&'static str>,
+}
+
+impl HtmlWithLimit {
+    /// Create a new buffer, with a limit of `length_limit`.
+    pub(super) fn new(length_limit: usize) -> Self {
+        let buf = if length_limit > 1000 {
+            // If the length limit is really large, don't preallocate tons of memory.
+            String::new()
+        } else {
+            // The length limit is actually a good heuristic for initial allocation size.
+            // Measurements showed that using it as the initial capacity ended up using less memory
+            // than `String::new`.
+            // See https://github.com/rust-lang/rust/pull/88173#discussion_r692531631 for more.
+            String::with_capacity(length_limit)
+        };
+        Self {
+            buf,
+            len: 0,
+            limit: length_limit,
+            unclosed_tags: Vec::new(),
+            queued_tags: Vec::new(),
+        }
+    }
+
+    /// Finish using the buffer and get the written output.
+    /// This function will close all unclosed tags for you.
+    pub(super) fn finish(mut self) -> String {
+        self.close_all_tags();
+        self.buf
+    }
+
+    /// Write some plain text to the buffer, escaping as needed.
+    ///
+    /// This function skips writing the text if the length limit was reached
+    /// and returns [`ControlFlow::Break`].
+    pub(super) fn push(&mut self, text: &str) -> ControlFlow<(), ()> {
+        if self.len + text.len() > self.limit {
+            return ControlFlow::BREAK;
+        }
+
+        self.flush_queue();
+        write!(self.buf, "{}", Escape(text)).unwrap();
+        self.len += text.len();
+
+        ControlFlow::CONTINUE
+    }
+
+    /// Open an HTML tag.
+    ///
+    /// **Note:** HTML attributes have not yet been implemented.
+    /// This function will panic if called with a non-alphabetic `tag_name`.
+    pub(super) fn open_tag(&mut self, tag_name: &'static str) {
+        assert!(
+            tag_name.chars().all(|c| ('a'..='z').contains(&c)),
+            "tag_name contained non-alphabetic chars: {:?}",
+            tag_name
+        );
+        self.queued_tags.push(tag_name);
+    }
+
+    /// Close the most recently opened HTML tag.
+    pub(super) fn close_tag(&mut self) {
+        match self.unclosed_tags.pop() {
+            // Close the most recently opened tag.
+            Some(tag_name) => write!(self.buf, "</{}>", tag_name).unwrap(),
+            // There are valid cases where `close_tag()` is called without
+            // there being any tags to close. For example, this occurs when
+            // a tag is opened after the length limit is exceeded;
+            // `flush_queue()` will never be called, and thus, the tag will
+            // not end up being added to `unclosed_tags`.
+            None => {}
+        }
+    }
+
+    /// Write all queued tags and add them to the `unclosed_tags` list.
+    fn flush_queue(&mut self) {
+        for tag_name in self.queued_tags.drain(..) {
+            write!(self.buf, "<{}>", tag_name).unwrap();
+
+            self.unclosed_tags.push(tag_name);
+        }
+    }
+
+    /// Close all unclosed tags.
+    fn close_all_tags(&mut self) {
+        while !self.unclosed_tags.is_empty() {
+            self.close_tag();
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs
new file mode 100644 (file)
index 0000000..2d02b8a
--- /dev/null
@@ -0,0 +1,120 @@
+use super::*;
+
+#[test]
+fn empty() {
+    assert_eq!(HtmlWithLimit::new(0).finish(), "");
+    assert_eq!(HtmlWithLimit::new(60).finish(), "");
+}
+
+#[test]
+fn basic() {
+    let mut buf = HtmlWithLimit::new(60);
+    buf.push("Hello ");
+    buf.open_tag("em");
+    buf.push("world");
+    buf.close_tag();
+    buf.push("!");
+    assert_eq!(buf.finish(), "Hello <em>world</em>!");
+}
+
+#[test]
+fn no_tags() {
+    let mut buf = HtmlWithLimit::new(60);
+    buf.push("Hello");
+    buf.push(" world!");
+    assert_eq!(buf.finish(), "Hello world!");
+}
+
+#[test]
+fn limit_0() {
+    let mut buf = HtmlWithLimit::new(0);
+    buf.push("Hello ");
+    buf.open_tag("em");
+    buf.push("world");
+    buf.close_tag();
+    buf.push("!");
+    assert_eq!(buf.finish(), "");
+}
+
+#[test]
+fn exactly_limit() {
+    let mut buf = HtmlWithLimit::new(12);
+    buf.push("Hello ");
+    buf.open_tag("em");
+    buf.push("world");
+    buf.close_tag();
+    buf.push("!");
+    assert_eq!(buf.finish(), "Hello <em>world</em>!");
+}
+
+#[test]
+fn multiple_nested_tags() {
+    let mut buf = HtmlWithLimit::new(60);
+    buf.open_tag("p");
+    buf.push("This is a ");
+    buf.open_tag("em");
+    buf.push("paragraph");
+    buf.open_tag("strong");
+    buf.push("!");
+    buf.close_tag();
+    buf.close_tag();
+    buf.close_tag();
+    assert_eq!(buf.finish(), "<p>This is a <em>paragraph<strong>!</strong></em></p>");
+}
+
+#[test]
+fn forgot_to_close_tags() {
+    let mut buf = HtmlWithLimit::new(60);
+    buf.open_tag("p");
+    buf.push("This is a ");
+    buf.open_tag("em");
+    buf.push("paragraph");
+    buf.open_tag("strong");
+    buf.push("!");
+    assert_eq!(buf.finish(), "<p>This is a <em>paragraph<strong>!</strong></em></p>");
+}
+
+#[test]
+fn past_the_limit() {
+    let mut buf = HtmlWithLimit::new(20);
+    buf.open_tag("p");
+    (0..10).try_for_each(|n| {
+        buf.open_tag("strong");
+        buf.push("word#")?;
+        buf.push(&n.to_string())?;
+        buf.close_tag();
+        ControlFlow::CONTINUE
+    });
+    buf.close_tag();
+    assert_eq!(
+        buf.finish(),
+        "<p>\
+             <strong>word#0</strong>\
+             <strong>word#1</strong>\
+             <strong>word#2</strong>\
+             </p>"
+    );
+}
+
+#[test]
+fn quickly_past_the_limit() {
+    let mut buf = HtmlWithLimit::new(6);
+    buf.open_tag("p");
+    buf.push("Hello");
+    buf.push(" World");
+    // intentionally not closing <p> before finishing
+    assert_eq!(buf.finish(), "<p>Hello</p>");
+}
+
+#[test]
+fn close_too_many() {
+    let mut buf = HtmlWithLimit::new(60);
+    buf.open_tag("p");
+    buf.push("Hello");
+    buf.close_tag();
+    // This call does not panic because there are valid cases
+    // where `close_tag()` is called with no tags left to close.
+    // So `close_tag()` does nothing in this case.
+    buf.close_tag();
+    assert_eq!(buf.finish(), "<p>Hello</p>");
+}
index 7c6d7dff816d539ed77a69521fca2df775dbfa36..aa3723eddfcce9473e0bae8107b9945c32882c4a 100644 (file)
 use rustc_middle::ty::TyCtxt;
 use rustc_span::edition::Edition;
 use rustc_span::Span;
+
 use std::borrow::Cow;
 use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::Write;
-use std::ops::Range;
+use std::ops::{ControlFlow, Range};
 use std::str;
 
 use crate::clean::RenderedLink;
@@ -36,6 +37,7 @@
 use crate::html::escape::Escape;
 use crate::html::format::Buffer;
 use crate::html::highlight;
+use crate::html::length_limit::HtmlWithLimit;
 use crate::html::toc::TocBuilder;
 
 use pulldown_cmark::{
@@ -1081,15 +1083,6 @@ fn markdown_summary_with_limit(
         return (String::new(), false);
     }
 
-    let mut s = String::with_capacity(md.len() * 3 / 2);
-    let mut text_length = 0;
-    let mut stopped_early = false;
-
-    fn push(s: &mut String, text_length: &mut usize, text: &str) {
-        write!(s, "{}", Escape(text)).unwrap();
-        *text_length += text.len();
-    }
-
     let mut replacer = |broken_link: BrokenLink<'_>| {
         if let Some(link) =
             link_names.iter().find(|link| &*link.original_text == broken_link.reference)
@@ -1101,56 +1094,48 @@ fn push(s: &mut String, text_length: &mut usize, text: &str) {
     };
 
     let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
-    let p = LinkReplacer::new(p, link_names);
+    let mut p = LinkReplacer::new(p, link_names);
 
-    'outer: for event in p {
+    let mut buf = HtmlWithLimit::new(length_limit);
+    let mut stopped_early = false;
+    p.try_for_each(|event| {
         match &event {
             Event::Text(text) => {
-                for word in text.split_inclusive(char::is_whitespace) {
-                    if text_length + word.len() >= length_limit {
-                        stopped_early = true;
-                        break 'outer;
-                    }
-
-                    push(&mut s, &mut text_length, word);
+                let r =
+                    text.split_inclusive(char::is_whitespace).try_for_each(|word| buf.push(word));
+                if r.is_break() {
+                    stopped_early = true;
                 }
+                return r;
             }
             Event::Code(code) => {
-                if text_length + code.len() >= length_limit {
+                buf.open_tag("code");
+                let r = buf.push(code);
+                if r.is_break() {
                     stopped_early = true;
-                    break;
+                } else {
+                    buf.close_tag();
                 }
-
-                s.push_str("<code>");
-                push(&mut s, &mut text_length, code);
-                s.push_str("</code>");
+                return r;
             }
             Event::Start(tag) => match tag {
-                Tag::Emphasis => s.push_str("<em>"),
-                Tag::Strong => s.push_str("<strong>"),
-                Tag::CodeBlock(..) => break,
+                Tag::Emphasis => buf.open_tag("em"),
+                Tag::Strong => buf.open_tag("strong"),
+                Tag::CodeBlock(..) => return ControlFlow::BREAK,
                 _ => {}
             },
             Event::End(tag) => match tag {
-                Tag::Emphasis => s.push_str("</em>"),
-                Tag::Strong => s.push_str("</strong>"),
-                Tag::Paragraph => break,
-                Tag::Heading(..) => break,
+                Tag::Emphasis | Tag::Strong => buf.close_tag(),
+                Tag::Paragraph | Tag::Heading(..) => return ControlFlow::BREAK,
                 _ => {}
             },
-            Event::HardBreak | Event::SoftBreak => {
-                if text_length + 1 >= length_limit {
-                    stopped_early = true;
-                    break;
-                }
-
-                push(&mut s, &mut text_length, " ");
-            }
+            Event::HardBreak | Event::SoftBreak => buf.push(" ")?,
             _ => {}
-        }
-    }
+        };
+        ControlFlow::CONTINUE
+    });
 
-    (s, stopped_early)
+    (buf.finish(), stopped_early)
 }
 
 /// Renders a shortened first paragraph of the given Markdown as a subset of Markdown,
index 1e4bdc2d15199525b173ed084984cfcc50ff04e2..eca75ef013aae89ea567c29552b16541de9c5799 100644 (file)
@@ -225,6 +225,7 @@ fn t(input: &str, expect: &str) {
         assert_eq!(output, expect, "original: {}", input);
     }
 
+    t("", "");
     t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
     t("*italic*", "<em>italic</em>");
     t("**bold**", "<strong>bold</strong>");
@@ -264,6 +265,7 @@ fn t(input: &str, expect: &str) {
         assert_eq!(output, expect, "original: {}", input);
     }
 
+    t("", "");
     t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
     t("**bold**", "bold");
     t("Multi-line\nsummary", "Multi-line summary");
index 60ebdf5690d0d2aa9fffa476f38826a454767545..109b0a356db5ff26f352701edea20ba12f152462 100644 (file)
@@ -2,6 +2,7 @@
 crate mod format;
 crate mod highlight;
 crate mod layout;
+mod length_limit;
 // used by the error-index generator, so it needs to be public
 pub mod markdown;
 crate mod render;
index 6ce0828e159402b867eb447921efc0d2e6ada44c..733bedfdde9b487d2eee214069d469513a5fe366 100644 (file)
     ///
     /// [#82381]: https://github.com/rust-lang/rust/issues/82381
     crate shared: Rc<SharedContext<'tcx>>,
-    /// The [`Cache`] used during rendering.
-    ///
-    /// Ideally the cache would be in [`SharedContext`], but it's mutated
-    /// between when the `SharedContext` is created and when `Context`
-    /// is created, so more refactoring would be needed.
-    ///
-    /// It's immutable once in `Context`, so it's not as bad that it's not in
-    /// `SharedContext`.
-    // FIXME: move `cache` to `SharedContext`
-    crate cache: Rc<Cache>,
     /// This flag indicates whether `[src]` links should be generated or not. If
     /// the source files are present in the html rendering, then this will be
     /// `true`.
@@ -80,7 +70,7 @@
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
 #[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Context<'_>, 112);
+rustc_data_structures::static_assert_size!(Context<'_>, 104);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
 crate struct SharedContext<'tcx> {
     /// Correspondance map used to link types used in the source code pages to allow to click on
     /// links to jump to the type's definition.
     crate span_correspondance_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
+    /// The [`Cache`] used during rendering.
+    crate cache: Cache,
 }
 
 impl SharedContext<'_> {
@@ -162,7 +154,7 @@ pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
     }
 
     pub(crate) fn cache(&self) -> &Cache {
-        &self.cache
+        &self.shared.cache
     }
 
     pub(super) fn sess(&self) -> &'tcx Session {
@@ -237,7 +229,7 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
                 &self.shared.style_files,
             )
         } else {
-            if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_def_id()) {
+            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.def_id.expect_def_id()) {
                 let mut path = String::new();
                 for name in &names[..names.len() - 1] {
                     path.push_str(name);
@@ -326,7 +318,7 @@ pub(super) fn src_href(&self, item: &clean::Item) -> Option<String> {
                 return None;
             }
         } else {
-            let (krate, src_root) = match *self.cache.extern_locations.get(&cnum)? {
+            let (krate, src_root) = match *self.cache().extern_locations.get(&cnum)? {
                 ExternalLocation::Local => {
                     let e = ExternalCrate { crate_num: cnum };
                     (e.name(self.tcx()), e.src_root(self.tcx()))
@@ -487,6 +479,7 @@ fn init(
             show_type_layout,
             templates,
             span_correspondance_map: matches,
+            cache,
         };
 
         // Add the default themes to the `Vec` of stylepaths
@@ -511,7 +504,6 @@ fn init(
             render_redirect_pages: false,
             id_map: RefCell::new(id_map),
             shared: Rc::new(scx),
-            cache: Rc::new(cache),
             include_sources,
         };
 
@@ -520,7 +512,7 @@ fn init(
         }
 
         // Build our search index
-        let index = build_index(&krate, Rc::get_mut(&mut cx.cache).unwrap(), tcx);
+        let index = build_index(&krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
 
         // Write shared runs within a flock; disable thread dispatching of IO temporarily.
         Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
@@ -536,7 +528,6 @@ fn make_child_renderer(&self) -> Self {
             render_redirect_pages: self.render_redirect_pages,
             id_map: RefCell::new(IdMap::new()),
             shared: Rc::clone(&self.shared),
-            cache: Rc::clone(&self.cache),
             include_sources: self.include_sources,
         }
     }
@@ -561,7 +552,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
             extra_scripts: &[],
             static_extra_scripts: &[],
         };
-        let sidebar = if let Some(ref version) = self.cache.crate_version {
+        let sidebar = if let Some(ref version) = self.shared.cache.crate_version {
             format!(
                 "<h2 class=\"location\">Crate {}</h2>\
                      <div class=\"block version\">\
@@ -722,7 +713,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
     }
 
     fn cache(&self) -> &Cache {
-        &self.cache
+        &self.shared.cache
     }
 }
 
index fd2e18a8be77f0d3933d14c4e1174076649ec3d6..172fe5d164b7afc1f123971b97a2d7fa5b8b4d76 100644 (file)
@@ -710,11 +710,15 @@ fn render_impls(
                 containing_item,
                 assoc_link,
                 RenderMode::Normal,
-                true,
                 None,
-                false,
-                true,
                 &[],
+                ImplRenderingParameters {
+                    show_def_docs: true,
+                    is_on_foreign_type: false,
+                    show_default_items: true,
+                    show_non_assoc_items: true,
+                    toggle_open_by_default: true,
+                },
             );
             buffer.into_inner()
         })
@@ -753,7 +757,7 @@ fn assoc_const(
 ) {
     write!(
         w,
-        "{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
+        "{}{}const <a href=\"{}\" class=\"constant\">{}</a>: {}",
         extra,
         it.visibility.print_with_space(it.def_id, cx),
         naive_assoc_href(it, link, cx),
@@ -1012,11 +1016,11 @@ fn render_assoc_items(
     what: AssocItemRender<'_>,
 ) {
     info!("Documenting associated items of {:?}", containing_item.name);
-    let v = match cx.cache.impls.get(&it) {
+    let cache = cx.cache();
+    let v = match cache.impls.get(&it) {
         Some(v) => v,
         None => return,
     };
-    let cache = cx.cache();
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
         let render_mode = match what {
@@ -1049,11 +1053,15 @@ fn render_assoc_items(
                 containing_item,
                 AssocItemLink::Anchor(None),
                 render_mode,
-                true,
                 None,
-                false,
-                true,
                 &[],
+                ImplRenderingParameters {
+                    show_def_docs: true,
+                    is_on_foreign_type: false,
+                    show_default_items: true,
+                    show_non_assoc_items: true,
+                    toggle_open_by_default: true,
+                },
             );
         }
     }
@@ -1063,11 +1071,11 @@ fn render_assoc_items(
     if !traits.is_empty() {
         let deref_impl = traits
             .iter()
-            .find(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did);
+            .find(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did);
         if let Some(impl_) = deref_impl {
             let has_deref_mut = traits
                 .iter()
-                .any(|t| t.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_mut_trait_did);
+                .any(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_mut_trait_did);
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -1122,6 +1130,7 @@ fn render_deref_methods(
     container_item: &clean::Item,
     deref_mut: bool,
 ) {
+    let cache = cx.cache();
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
     let (target, real_target) = impl_
         .inner_impl()
@@ -1138,8 +1147,8 @@ fn render_deref_methods(
     debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
-    if let Some(did) = target.def_id_full(cx.cache()) {
-        if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
+    if let Some(did) = target.def_id_full(cache) {
+        if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cache) {
             // `impl Deref<Target = S> for S`
             if did == type_did {
                 // Avoid infinite cycles
@@ -1149,7 +1158,7 @@ fn render_deref_methods(
         render_assoc_items(w, cx, container_item, did, what);
     } else {
         if let Some(prim) = target.primitive_type() {
-            if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
+            if let Some(&did) = cache.primitive_locations.get(&prim) {
                 render_assoc_items(w, cx, container_item, did, what);
             }
         }
@@ -1242,6 +1251,16 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
     out.into_inner()
 }
 
+#[derive(Clone, Copy, Debug)]
+struct ImplRenderingParameters {
+    show_def_docs: bool,
+    is_on_foreign_type: bool,
+    show_default_items: bool,
+    /// Whether or not to show methods.
+    show_non_assoc_items: bool,
+    toggle_open_by_default: bool,
+}
+
 fn render_impl(
     w: &mut Buffer,
     cx: &Context<'_>,
@@ -1249,13 +1268,9 @@ fn render_impl(
     parent: &clean::Item,
     link: AssocItemLink<'_>,
     render_mode: RenderMode,
-    show_def_docs: bool,
     use_absolute: Option<bool>,
-    is_on_foreign_type: bool,
-    show_default_items: bool,
-    // This argument is used to reference same type with different paths to avoid duplication
-    // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
+    rendering_params: ImplRenderingParameters,
 ) {
     let cache = cx.cache();
     let traits = &cache.traits;
@@ -1278,17 +1293,18 @@ fn doc_impl_item(
         render_mode: RenderMode,
         is_default_item: bool,
         trait_: Option<&clean::Trait>,
-        show_def_docs: bool,
+        rendering_params: ImplRenderingParameters,
     ) {
         let item_type = item.type_();
         let name = item.name.as_ref().unwrap();
 
-        let render_method_item = match render_mode {
-            RenderMode::Normal => true,
-            RenderMode::ForDeref { mut_: deref_mut_ } => {
-                should_render_item(&item, deref_mut_, &cx.cache)
-            }
-        };
+        let render_method_item = rendering_params.show_non_assoc_items
+            && match render_mode {
+                RenderMode::Normal => true,
+                RenderMode::ForDeref { mut_: deref_mut_ } => {
+                    should_render_item(&item, deref_mut_, cx.cache())
+                }
+            };
 
         let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" };
 
@@ -1311,18 +1327,32 @@ fn doc_impl_item(
                         } else {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(&mut doc_buffer, it, cx, link, parent, show_def_docs);
+                            document_short(
+                                &mut doc_buffer,
+                                it,
+                                cx,
+                                link,
+                                parent,
+                                rendering_params.show_def_docs,
+                            );
                         }
                     }
                 } else {
                     document_item_info(&mut info_buffer, cx, item, Some(parent));
-                    if show_def_docs {
+                    if rendering_params.show_def_docs {
                         document_full(&mut doc_buffer, item, cx);
                         short_documented = false;
                     }
                 }
             } else {
-                document_short(&mut doc_buffer, item, cx, link, parent, show_def_docs);
+                document_short(
+                    &mut doc_buffer,
+                    item,
+                    cx,
+                    link,
+                    parent,
+                    rendering_params.show_def_docs,
+                );
             }
         }
         let w = if short_documented && trait_.is_some() { interesting } else { boring };
@@ -1454,7 +1484,7 @@ fn doc_impl_item(
             render_mode,
             false,
             trait_.map(|t| &t.trait_),
-            show_def_docs,
+            rendering_params,
         );
     }
 
@@ -1467,7 +1497,7 @@ fn render_default_items(
         parent: &clean::Item,
         containing_item: &clean::Item,
         render_mode: RenderMode,
-        show_def_docs: bool,
+        rendering_params: ImplRenderingParameters,
     ) {
         for trait_item in &t.items {
             let n = trait_item.name;
@@ -1489,7 +1519,7 @@ fn render_default_items(
                 render_mode,
                 true,
                 Some(t),
-                show_def_docs,
+                rendering_params,
             );
         }
     }
@@ -1498,7 +1528,7 @@ fn render_default_items(
     // default items which weren't overridden in the implementation block.
     // We don't emit documentation for default items if they appear in the
     // Implementations on Foreign Types or Implementors sections.
-    if show_default_items {
+    if rendering_params.show_default_items {
         if let Some(t) = trait_ {
             render_default_items(
                 &mut default_impl_items,
@@ -1509,7 +1539,7 @@ fn render_default_items(
                 &i.impl_item,
                 parent,
                 render_mode,
-                show_def_docs,
+                rendering_params,
             );
         }
     }
@@ -1517,7 +1547,11 @@ fn render_default_items(
         let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
         if toggled {
             close_tags.insert_str(0, "</details>");
-            write!(w, "<details class=\"rustdoc-toggle implementors-toggle\" open>");
+            write!(
+                w,
+                "<details class=\"rustdoc-toggle implementors-toggle\"{}>",
+                if rendering_params.toggle_open_by_default { " open" } else { "" }
+            );
             write!(w, "<summary>")
         }
         render_impl_summary(
@@ -1526,9 +1560,9 @@ fn render_default_items(
             i,
             parent,
             parent,
-            show_def_docs,
+            rendering_params.show_def_docs,
             use_absolute,
-            is_on_foreign_type,
+            rendering_params.is_on_foreign_type,
             aliases,
         );
         if toggled {
@@ -1678,7 +1712,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     }
 
     if it.is_crate() {
-        if let Some(ref version) = cx.cache.crate_version {
+        if let Some(ref version) = cx.cache().crate_version {
             write!(
                 buffer,
                 "<div class=\"block version\">\
@@ -1825,18 +1859,16 @@ fn small_url_encode(s: String) -> String {
 
 fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
     let did = it.def_id.expect_def_id();
-    if let Some(v) = cx.cache.impls.get(&did) {
+    let cache = cx.cache();
+    if let Some(v) = cache.impls.get(&did) {
         let mut used_links = FxHashSet::default();
-        let cache = cx.cache();
 
         {
             let used_links_bor = &mut used_links;
             let mut ret = v
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
-                .flat_map(move |i| {
-                    get_methods(i.inner_impl(), false, used_links_bor, false, &cx.cache)
-                })
+                .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false, cache))
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 // We want links' order to be reproducible so we don't use unstable sort.
@@ -1857,7 +1889,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             if let Some(impl_) = v
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_some())
-                .find(|i| i.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did)
+                .find(|i| i.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did)
             {
                 sidebar_deref_methods(cx, out, impl_, v);
             }
@@ -2117,15 +2149,15 @@ fn print_sidebar_section(
         "</div>",
     );
 
-    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
-        let cache = cx.cache();
+    let cache = cx.cache();
+    if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
         let mut res = implementors
             .iter()
             .filter(|i| {
                 i.inner_impl()
                     .for_
                     .def_id_full(cache)
-                    .map_or(false, |d| !cx.cache.paths.contains_key(&d))
+                    .map_or(false, |d| !cache.paths.contains_key(&d))
             })
             .filter_map(|i| extract_for_impl_name(&i.impl_item, cx))
             .collect::<Vec<_>>();
index 96cc67ce97c756a44c8757f0dbdce9a3297471e0..39ef641a3ace2772681b7e3bea91b478aee50d4f 100644 (file)
@@ -16,8 +16,8 @@
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
     render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
-    render_impl, render_impl_summary, render_stability_since_raw, write_srclink, AssocItemLink,
-    Context,
+    render_impl, render_stability_since_raw, write_srclink, AssocItemLink, Context,
+    ImplRenderingParameters,
 };
 use crate::clean::{self, GetDefId};
 use crate::formats::item_type::ItemType;
@@ -690,7 +690,8 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
     // If there are methods directly on this trait object, render them here.
     render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
 
-    if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
+    let cache = cx.cache();
+    if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
         // The DefId is for the first Type found with that name. The bool is
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
@@ -712,10 +713,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         }
 
         let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| {
-            i.inner_impl()
-                .for_
-                .def_id_full(cx.cache())
-                .map_or(true, |d| cx.cache.paths.contains_key(&d))
+            i.inner_impl().for_.def_id_full(cache).map_or(true, |d| cache.paths.contains_key(&d))
         });
 
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -738,11 +736,15 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
                     it,
                     assoc_link,
                     RenderMode::Normal,
-                    false,
                     None,
-                    true,
-                    false,
                     &[],
+                    ImplRenderingParameters {
+                        show_def_docs: false,
+                        is_on_foreign_type: true,
+                        show_default_items: false,
+                        show_non_assoc_items: true,
+                        toggle_open_by_default: false,
+                    },
                 );
             }
         }
@@ -772,7 +774,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
                     it,
                     w,
                     &implementor_dups,
-                    &collect_paths_for_type(implementor.inner_impl().for_.clone(), &cx.cache),
+                    &collect_paths_for_type(implementor.inner_impl().for_.clone(), cache),
                 );
             }
             w.write_str("</div>");
@@ -806,7 +808,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item
         path = if it.def_id.is_local() {
             cx.current.join("/")
         } else {
-            let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_def_id()];
+            let (ref path, _) = cache.external_paths[&it.def_id.expect_def_id()];
             path[..path.len() - 1].join("/")
         },
         ty = it.type_(),
@@ -939,6 +941,19 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
     document_type_layout(w, cx, def_id);
 }
 
+fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
+    for (i, ty) in s
+        .iter()
+        .map(|f| if let clean::StructFieldItem(ref ty) = *f.kind { ty } else { unreachable!() })
+        .enumerate()
+    {
+        if i > 0 {
+            w.write_str(",&nbsp;");
+        }
+        write!(w, "{}", ty.print(cx));
+    }
+}
+
 fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
     wrap_into_docblock(w, |w| {
         wrap_item(w, "enum", |w| {
@@ -966,14 +981,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     match *v.kind {
                         clean::VariantItem(ref var) => match var {
                             clean::Variant::CLike => write!(w, "{}", name),
-                            clean::Variant::Tuple(ref tys) => {
+                            clean::Variant::Tuple(ref s) => {
                                 write!(w, "{}(", name);
-                                for (i, ty) in tys.iter().enumerate() {
-                                    if i > 0 {
-                                        w.write_str(",&nbsp;")
-                                    }
-                                    write!(w, "{}", ty.print(cx));
-                                }
+                                print_tuple_struct_fields(w, cx, s);
                                 w.write_str(")");
                             }
                             clean::Variant::Struct(ref s) => {
@@ -1026,14 +1036,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 id = id,
                 name = variant.name.as_ref().unwrap()
             );
-            if let clean::VariantItem(clean::Variant::Tuple(ref tys)) = *variant.kind {
+            if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
                 w.write_str("(");
-                for (i, ty) in tys.iter().enumerate() {
-                    if i > 0 {
-                        w.write_str(",&nbsp;");
-                    }
-                    write!(w, "{}", ty.print(cx));
-                }
+                print_tuple_struct_fields(w, cx, s);
                 w.write_str(")");
             }
             w.write_str("</code>");
@@ -1043,7 +1048,11 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             document_non_exhaustive(w, variant);
 
             use crate::clean::Variant;
-            if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
+            if let Some((extra, fields)) = match *variant.kind {
+                clean::VariantItem(Variant::Struct(ref s)) => Some(("", &s.fields)),
+                clean::VariantItem(Variant::Tuple(ref fields)) => Some(("Tuple ", fields)),
+                _ => None,
+            } {
                 let variant_id = cx.derive_id(format!(
                     "{}.{}.fields",
                     ItemType::Variant,
@@ -1053,10 +1062,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                 write!(
                     w,
                     "<h3>{extra}Fields of <b>{name}</b></h3><div>",
-                    extra = if s.struct_type == CtorKind::Fn { "Tuple " } else { "" },
+                    extra = extra,
                     name = variant.name.as_ref().unwrap(),
                 );
-                for field in &s.fields {
+                for field in fields {
                     use crate::clean::StructFieldItem;
                     if let StructFieldItem(ref ty) = *field.kind {
                         let id = cx.derive_id(format!(
@@ -1390,16 +1399,22 @@ fn render_implementor(
         } => implementor_dups[&path.last()].1,
         _ => false,
     };
-    render_impl_summary(
+    render_impl(
         w,
         cx,
         implementor,
         trait_,
-        trait_,
-        false,
+        AssocItemLink::Anchor(None),
+        RenderMode::Normal,
         Some(use_absolute),
-        false,
         aliases,
+        ImplRenderingParameters {
+            show_def_docs: false,
+            is_on_foreign_type: false,
+            show_default_items: false,
+            show_non_assoc_items: false,
+            toggle_open_by_default: false,
+        },
     );
 }
 
index b35cd45dc9a886c60979dd15ba134df14b162a6a..54476d9c9a459f19b34179f57caa25512baf5159 100644 (file)
@@ -45,7 +45,7 @@
 
     if include_sources {
         if generate_link_to_definition {
-            intravisit::walk_crate(&mut visitor, tcx.hir().krate());
+            tcx.hir().walk_toplevel_module(&mut visitor);
         }
         let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
         (krate, sources, visitor.matches)
index c16769c474a2124b5abf63d5ddf17d41427f1bbc..99cd98f7eaeb84592f18d3287bc35f85cef10842 100644 (file)
@@ -518,7 +518,8 @@ fn to_json_string(&self) -> String {
 
     // Update the list of all implementors for traits
     let dst = cx.dst.join("implementors");
-    for (&did, imps) in &cx.cache.implementors {
+    let cache = cx.cache();
+    for (&did, imps) in &cache.implementors {
         // Private modules can leak through to this phase of rustdoc, which
         // could contain implementations for otherwise private types. In some
         // rare cases we could find an implementation for an item which wasn't
@@ -526,9 +527,9 @@ fn to_json_string(&self) -> String {
         //
         // FIXME: this is a vague explanation for why this can't be a `get`, in
         //        theory it should be...
-        let &(ref remote_path, remote_item_type) = match cx.cache.paths.get(&did) {
+        let &(ref remote_path, remote_item_type) = match cache.paths.get(&did) {
             Some(p) => p,
-            None => match cx.cache.external_paths.get(&did) {
+            None => match cache.external_paths.get(&did) {
                 Some(p) => p,
                 None => continue,
             },
@@ -557,7 +558,7 @@ struct Implementor {
                     Some(Implementor {
                         text: imp.inner_impl().print(false, cx).to_string(),
                         synthetic: imp.inner_impl().synthetic,
-                        types: collect_paths_for_type(imp.inner_impl().for_.clone(), cx.cache()),
+                        types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
                     })
                 }
             })
@@ -566,7 +567,7 @@ struct Implementor {
         // Only create a js file if we have impls to add to it. If the trait is
         // documented locally though we always create the file to avoid dead
         // links.
-        if implementors.is_empty() && !cx.cache.paths.contains_key(&did) {
+        if implementors.is_empty() && !cache.paths.contains_key(&did) {
             continue;
         }
 
index 73916e204d9426aa805a9e8915f0ac5bdcccd83f..bb90b195ddd4f5547dfc9c19d79a12cac53736ec 100644 (file)
@@ -72,10 +72,9 @@ fn add_local_source(&mut self, item: &clean::Item) {
             href.push('/');
         });
 
-        let src_fname = p.file_name().expect("source has no filename").to_os_string();
-        let mut fname = src_fname.clone();
-        fname.push(".html");
-        href.push_str(&fname.to_string_lossy());
+        let mut src_fname = p.file_name().expect("source has no filename").to_os_string();
+        src_fname.push(".html");
+        href.push_str(&src_fname.to_string_lossy());
         self.local_sources.insert(p, href);
     }
 }
index dab6d655c6a874c5aa3e35839db36df9581074ea..f9ddef4120bbec8c69c0ba92ab2f3c854850f976 100644 (file)
@@ -40,7 +40,7 @@ h4 {
 .code-header {
        color: #e6e1cf;
 }
-pre > code {
+.docblock pre > code, pre > code {
        color: #e6e1cf;
 }
 span code {
index f3eeea6c6ae0be5b6c4aed560d6bb22a258cbe1b..e6bbd237cda7d72f2f1320ae442c05cc6936f320 100644 (file)
@@ -127,7 +127,7 @@ fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
             },
             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
                 inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(),
-                output: output.map(|a| a.into_tcx(tcx)),
+                output: output.map(|a| (*a).into_tcx(tcx)),
             },
         }
     }
@@ -139,7 +139,7 @@ fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
         match arg {
             Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
             Type(t) => GenericArg::Type(t.into_tcx(tcx)),
-            Const(c) => GenericArg::Const(c.into_tcx(tcx)),
+            Const(box c) => GenericArg::Const(c.into_tcx(tcx)),
             Infer => GenericArg::Infer,
         }
     }
@@ -326,7 +326,9 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
     fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
         use clean::GenericParamDefKind::*;
         match kind {
-            Lifetime => GenericParamDefKind::Lifetime,
+            Lifetime { outlives } => GenericParamDefKind::Lifetime {
+                outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
+            },
             Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
                 default: default.map(|x| x.into_tcx(tcx)),
@@ -569,7 +571,18 @@ fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
         use clean::Variant::*;
         match variant {
             CLike => Variant::Plain,
-            Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
+            Tuple(fields) => Variant::Tuple(
+                fields
+                    .into_iter()
+                    .map(|f| {
+                        if let clean::StructFieldItem(ty) = *f.kind {
+                            ty.into_tcx(tcx)
+                        } else {
+                            unreachable!()
+                        }
+                    })
+                    .collect(),
+            ),
             Struct(s) => Variant::Struct(ids(s.fields)),
         }
     }
index 8bdf1a598123043e08f7595f818b7633b920b5d3..5089cc30a1e398cb907aa45f6e585b0eed81572e 100644 (file)
@@ -234,7 +234,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
                     )
                 })
                 .collect(),
-            format_version: 6,
+            format_version: 7,
         };
         let mut p = self.out_path.clone();
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
index 34fe808dae2e4c5be2dd2df1550cc26b07c622c3..2dbe4c42b888ebcd1251167c7fb97f75d036c0ce 100644 (file)
@@ -4,7 +4,9 @@
 )]
 #![feature(rustc_private)]
 #![feature(array_methods)]
+#![feature(assert_matches)]
 #![feature(box_patterns)]
+#![feature(control_flow_enum)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(test)]
@@ -12,7 +14,6 @@
 #![feature(never_type)]
 #![feature(once_cell)]
 #![feature(type_ascription)]
-#![feature(iter_intersperse)]
 #![recursion_limit = "256"]
 #![warn(rustc::internal)]
 
@@ -30,6 +31,7 @@
 // Dependencies listed in Cargo.toml do not need `extern crate`.
 
 extern crate rustc_ast;
+extern crate rustc_ast_lowering;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
 extern crate rustc_data_structures;
@@ -503,10 +505,11 @@ fn opts() -> Vec<RustcOptGroup> {
         unstable("disable-minification", |o| {
             o.optflagmulti("", "disable-minification", "Disable minification applied on JS files")
         }),
-        stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "OPT")),
-        stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "OPT")),
-        stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "OPT")),
-        stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "OPT")),
+        stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")),
+        stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")),
+        stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")),
+        stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "LINT")),
+        stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "LINT")),
         stable("cap-lints", |o| {
             o.optmulti(
                 "",
@@ -517,14 +520,6 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
-        unstable("force-warn", |o| {
-            o.optopt(
-                "",
-                "force-warn",
-                "Lints that will warn even if allowed somewhere else",
-                "LINTS",
-            )
-        }),
         unstable("index-page", |o| {
             o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
         }),
@@ -731,7 +726,6 @@ fn main_options(options: config::Options) -> MainResult {
     let default_passes = options.default_passes;
     let output_format = options.output_format;
     // FIXME: fix this clone (especially render_options)
-    let externs = options.externs.clone();
     let manual_passes = options.manual_passes.clone();
     let render_options = options.render_options.clone();
     let config = core::create_config(options);
@@ -749,7 +743,7 @@ fn main_options(options: config::Options) -> MainResult {
             // We need to hold on to the complete resolver, so we cause everything to be
             // cloned for the analysis passes to use. Suboptimal, but necessary in the
             // current architecture.
-            let resolver = core::create_resolver(externs, queries, &sess);
+            let resolver = core::create_resolver(queries, &sess);
 
             if sess.has_errors() {
                 sess.fatal("Compilation failed, aborting rustdoc");
index 807872ae4fde361d722187706e2a8449845ec34d..178c8c15a158861ca6483398e43650bf6c08f113 100644 (file)
@@ -37,6 +37,9 @@
 use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
 use crate::passes::Pass;
 
+mod early;
+crate use early::load_intra_link_crates;
+
 crate const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
     name: "collect-intra-doc-links",
     run: collect_intra_doc_links,
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
new file mode 100644 (file)
index 0000000..cd90528
--- /dev/null
@@ -0,0 +1,75 @@
+use rustc_ast as ast;
+use rustc_hir::def::Namespace::TypeNS;
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_interface::interface;
+use rustc_span::Span;
+
+use std::cell::RefCell;
+use std::mem;
+use std::rc::Rc;
+
+type Resolver = Rc<RefCell<interface::BoxedResolver>>;
+// Letting the resolver escape at the end of the function leads to inconsistencies between the
+// crates the TyCtxt sees and the resolver sees (because the resolver could load more crates
+// after escaping). Hopefully `IntraLinkCrateLoader` gets all the crates we need ...
+crate fn load_intra_link_crates(resolver: Resolver, krate: &ast::Crate) -> Resolver {
+    let mut loader = IntraLinkCrateLoader { current_mod: CRATE_DEF_ID, resolver };
+    // `walk_crate` doesn't visit the crate itself for some reason.
+    loader.load_links_in_attrs(&krate.attrs, krate.span);
+    ast::visit::walk_crate(&mut loader, krate);
+    loader.resolver
+}
+
+struct IntraLinkCrateLoader {
+    current_mod: LocalDefId,
+    resolver: Rc<RefCell<interface::BoxedResolver>>,
+}
+
+impl IntraLinkCrateLoader {
+    fn load_links_in_attrs(&mut self, attrs: &[ast::Attribute], span: Span) {
+        use crate::html::markdown::markdown_links;
+        use crate::passes::collect_intra_doc_links::preprocess_link;
+
+        // FIXME: this probably needs to consider inlining
+        let attrs = crate::clean::Attributes::from_ast(attrs, None);
+        for (parent_module, doc) in attrs.collapsed_doc_value_by_module_level() {
+            debug!(?doc);
+            for link in markdown_links(&doc.as_str()) {
+                debug!(?link.link);
+                let path_str = if let Some(Ok(x)) = preprocess_link(&link) {
+                    x.path_str
+                } else {
+                    continue;
+                };
+                self.resolver.borrow_mut().access(|resolver| {
+                    let _ = resolver.resolve_str_path_error(
+                        span,
+                        &path_str,
+                        TypeNS,
+                        parent_module.unwrap_or(self.current_mod.to_def_id()),
+                    );
+                });
+            }
+        }
+    }
+}
+
+impl ast::visit::Visitor<'_> for IntraLinkCrateLoader {
+    fn visit_item(&mut self, item: &ast::Item) {
+        use rustc_ast_lowering::ResolverAstLowering;
+
+        if let ast::ItemKind::Mod(..) = item.kind {
+            let new_mod =
+                self.resolver.borrow_mut().access(|resolver| resolver.local_def_id(item.id));
+            let old_mod = mem::replace(&mut self.current_mod, new_mod);
+
+            self.load_links_in_attrs(&item.attrs, item.span);
+            ast::visit::walk_item(self, item);
+
+            self.current_mod = old_mod;
+        } else {
+            self.load_links_in_attrs(&item.attrs, item.span);
+            ast::visit::walk_item(self, item);
+        }
+    }
+}
index 390ab1694a05bedd980a6ed5e43dce41db63167e..0e86fe45640f8ec80d728be3cd9aa536c7f02b06 100644 (file)
@@ -30,7 +30,7 @@
 mod propagate_doc_cfg;
 crate use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
 
-mod collect_intra_doc_links;
+crate mod collect_intra_doc_links;
 crate use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
 
 mod doc_test_lints;
index 4305268c9aab051991d6cff42ebff6ee46abf507..a93880453ba274916cca5561235e5179ac9da166 100644 (file)
@@ -40,6 +40,7 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             | clean::UnionItem(..)
             | clean::AssocConstItem(..)
             | clean::TraitAliasItem(..)
+            | clean::MacroItem(..)
             | clean::ForeignTypeItem => {
                 if i.def_id.is_local() {
                     if !self.access_levels.is_exported(i.def_id.expect_def_id()) {
@@ -70,8 +71,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
             clean::ImplItem(..) => {}
 
-            // tymethods/macros have no control over privacy
-            clean::MacroItem(..) | clean::TyMethodItem(..) => {}
+            // tymethods have no control over privacy
+            clean::TyMethodItem(..) => {}
 
             // Proc-macros are always public
             clean::ProcMacroItem(..) => {}
@@ -93,8 +94,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
             // implementations of traits are always public.
             clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
-            // Struct variant fields have inherited visibility
-            clean::VariantItem(clean::Variant::Struct(..)) => true,
+            // Variant fields have inherited visibility
+            clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true,
             _ => false,
         };
 
index e28910355357b29b50eb9c69fcbab79ee60b743c..897b9140fc8bcc6dfdc6aef07198cd5abd59908d 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
 use rustc_span;
-use rustc_span::def_id::LOCAL_CRATE;
+use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -79,49 +79,23 @@ fn store_path(&mut self, did: DefId) {
             &krate.module(),
             self.cx.tcx.crate_name(LOCAL_CRATE),
         );
-        // Attach the crate's exported macros to the top-level module.
-        // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
-        // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
-        // moving them back to their correct locations.
-        'exported_macros: for def in krate.exported_macros() {
-            // The `def` of a macro in `exported_macros` should correspond to either:
-            //  - a `#[macro_export] macro_rules!` macro,
-            //  - a built-in `derive` (or attribute) macro such as the ones in `::core`,
-            //  - a `pub macro`.
-            // Only the last two need to be fixed, thus:
-            if def.ast.macro_rules {
-                top_level_module.macros.push((def, None));
-                continue 'exported_macros;
-            }
-            let tcx = self.cx.tcx;
-            // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
-            // for the closest module _ancestor_, which is not necessarily a direct parent
-            // (since a direct parent isn't necessarily a module, c.f. #77828).
-            let macro_parent_def_id = {
-                use rustc_middle::ty::DefIdTree;
-                tcx.parent(def.def_id.to_def_id()).unwrap()
-            };
-            let macro_parent_path = tcx.def_path(macro_parent_def_id);
-            // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
-            // lookup the module by its name, by looking at each path segment one at a time.
-            let mut cur_mod = &mut top_level_module;
-            for path_segment in macro_parent_path.data {
-                // Path segments may refer to a module (in which case they belong to the type
-                // namespace), which is _necessary_ for the macro to be accessible outside it
-                // (no "associated macros" as of yet). Else we bail with an outer `continue`.
-                let path_segment_ty_ns = match path_segment.data {
-                    rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
-                    _ => continue 'exported_macros,
-                };
-                // Descend into the child module that matches this path segment (if any).
-                match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) {
-                    Some(child_mod) => cur_mod = &mut *child_mod,
-                    None => continue 'exported_macros,
+
+        // `#[macro_export] macro_rules!` items are reexported at the top level of the
+        // crate, regardless of where they're defined. We want to document the
+        // top level rexport of the macro, not its original definition, since
+        // the rexport defines the path that a user will actually see. Accordingly,
+        // we add the rexport as an item here, and then skip over the original
+        // definition in `visit_item()` below.
+        for export in self.cx.tcx.module_exports(CRATE_DEF_ID).unwrap_or(&[]) {
+            if let Res::Def(DefKind::Macro(_), def_id) = export.res {
+                if let Some(local_def_id) = def_id.as_local() {
+                    if self.cx.tcx.has_attr(def_id, sym::macro_export) {
+                        let hir_id = self.cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
+                        let item = self.cx.tcx.hir().expect_item(hir_id);
+                        top_level_module.items.push((item, None));
+                    }
                 }
             }
-            let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id();
-            assert_eq!(cur_mod_def_id, macro_parent_def_id);
-            cur_mod.macros.push((def, None));
         }
         self.cx.cache.exact_paths = self.exact_paths;
         top_level_module
@@ -238,10 +212,6 @@ fn maybe_inline_local(
                 self.inlining = prev;
                 true
             }
-            Node::MacroDef(def) if !glob => {
-                om.macros.push((def, renamed));
-                true
-            }
             _ => false,
         };
         self.view_item_stack.remove(&res_hir_id);
@@ -257,7 +227,10 @@ fn visit_item(
         debug!("visiting item {:?}", item);
         let name = renamed.unwrap_or(item.ident.name);
 
-        if item.vis.node.is_pub() {
+        let def_id = item.def_id.to_def_id();
+        let is_pub = item.vis.node.is_pub() || self.cx.tcx.has_attr(def_id, sym::macro_export);
+
+        if is_pub {
             self.store_path(item.def_id.to_def_id());
         }
 
@@ -269,7 +242,7 @@ fn visit_item(
                 }
             }
             // If we're inlining, skip private items.
-            _ if self.inlining && !item.vis.node.is_pub() => {}
+            _ if self.inlining && !is_pub => {}
             hir::ItemKind::GlobalAsm(..) => {}
             hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
             hir::ItemKind::Use(ref path, kind) => {
@@ -285,7 +258,7 @@ fn visit_item(
 
                 // If there was a private module in the current path then don't bother inlining
                 // anything as it will probably be stripped anyway.
-                if item.vis.node.is_pub() && self.inside_public_path {
+                if is_pub && self.inside_public_path {
                     let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
                         Some(ref list) if item.has_name(sym::doc) => {
                             list.iter().any(|i| i.has_name(sym::inline))
@@ -307,6 +280,26 @@ fn visit_item(
 
                 om.items.push((item, renamed))
             }
+            hir::ItemKind::Macro(ref macro_def) => {
+                // `#[macro_export] macro_rules!` items are handled seperately in `visit()`,
+                // above, since they need to be documented at the module top level. Accordingly,
+                // we only want to handle macros if one of three conditions holds:
+                //
+                // 1. This macro was defined by `macro`, and thus isn't covered by the case
+                //    above.
+                // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered
+                //    by the case above.
+                // 3. We're inlining, since a reexport where inlining has been requested
+                //    should be inlined even if it is also documented at the top level.
+
+                let def_id = item.def_id.to_def_id();
+                let is_macro_2_0 = !macro_def.macro_rules;
+                let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);
+
+                if is_macro_2_0 || nonexported || self.inlining {
+                    om.items.push((item, renamed));
+                }
+            }
             hir::ItemKind::Mod(ref m) => {
                 om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name));
             }
index e6c5dd473b7da567dc20ed3a635ca4dd2c6b7fb6..ec995b75d71c5f3b9a82fe084259477eb22f74da 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e6c5dd473b7da567dc20ed3a635ca4dd2c6b7fb6
+Subproject commit ec995b75d71c5f3b9a82fe084259477eb22f74da
index 38ba87322c2385f6d86c29f9b3c84e3b1c96de33..37cdc94441df7974d7cf1f0a68755835772c5629 100644 (file)
@@ -323,7 +323,7 @@ pub struct GenericParamDef {
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 #[serde(rename_all = "snake_case")]
 pub enum GenericParamDefKind {
-    Lifetime,
+    Lifetime { outlives: Vec<String> },
     Type { bounds: Vec<GenericBound>, default: Option<Type> },
     Const { ty: Type, default: Option<String> },
 }
index 1e263649e860a335d9291e76773e5c18db81f366..55ca8ee836c9844b566e2ffd6f52184f7649c881 100644 (file)
@@ -194,3 +194,15 @@ pub unsafe fn $func(x: $ty) -> $ty {
 // CHECK: fmr 0, 0
 // CHECK: #NO_APP
 check_reg!(reg_f64_f0, f64, "0", "f0", "fmr");
+
+// CHECK-LABEL: reg_f32_f18:
+// CHECK: #APP
+// CHECK: fmr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_f32_f18, f32, "18", "f18", "fmr");
+
+// CHECK-LABEL: reg_f64_f18:
+// CHECK: #APP
+// CHECK: fmr 18, 18
+// CHECK: #NO_APP
+check_reg!(reg_f64_f18, f64, "18", "f18", "fmr");
diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs
new file mode 100644 (file)
index 0000000..69d9cab
--- /dev/null
@@ -0,0 +1,168 @@
+// min-llvm-version: 10.0.1
+// revisions: s390x
+// assembly-output: emit-asm
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const i32;
+
+impl Copy for i8 {}
+impl Copy for u8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for f32 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+extern "C" {
+    fn extern_func();
+    static extern_static: u8;
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+    fn dont_merge(s: &str);
+}
+
+macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        dont_merge(stringify!($func));
+
+        let y;
+        asm!(concat!($mov," {}, {}"), out($class) y, in($class) x);
+        y
+    }
+};}
+
+macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
+    #[no_mangle]
+    pub unsafe fn $func(x: $ty) -> $ty {
+        dont_merge(stringify!($func));
+
+        let y;
+        asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x);
+        y
+    }
+};}
+
+// CHECK-LABEL: sym_fn_32:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_func
+// CHECK: #NO_APP
+#[cfg(s390x)]
+#[no_mangle]
+pub unsafe fn sym_fn_32() {
+    asm!("brasl %r14, {}", sym extern_func);
+}
+
+// CHECK-LABEL: sym_static:
+// CHECK: #APP
+// CHECK: brasl %r14, extern_static
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_static() {
+    asm!("brasl %r14, {}", sym extern_static);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8, i8, reg, "lgr");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16, i16, reg, "lgr");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32, i32, reg, "lgr");
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64, i64, reg, "lgr");
+
+// CHECK-LABEL: reg_f32:
+// CHECK: #APP
+// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f32, f32, freg, "ler");
+
+// CHECK-LABEL: reg_f64:
+// CHECK: #APP
+// CHECK: ldr %f{{[0-9]+}}, %f{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f64, f64, freg, "ldr");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_ptr, ptr, reg, "lgr");
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i8, i8, "r0", "lr");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i16, i16, "r0", "lr");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i32, i32, "r0", "lr");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: lr %r0, %r0
+// CHECK: #NO_APP
+check_reg!(r0_i64, i64, "r0", "lr");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: ler %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f32, f32, "f0", "ler");
+
+// CHECK-LABEL: f0_f64:
+// CHECK: #APP
+// CHECK: ldr %f0, %f0
+// CHECK: #NO_APP
+check_reg!(f0_f64, f64, "f0", "ldr");
diff --git a/src/test/codegen/asm-powerpc-clobbers.rs b/src/test/codegen/asm-powerpc-clobbers.rs
new file mode 100644 (file)
index 0000000..91a82c6
--- /dev/null
@@ -0,0 +1,48 @@
+// min-llvm-version: 10.0.1
+// revisions: powerpc powerpc64 powerpc64le
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//[powerpc64le] needs-llvm-components: powerpc
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+// CHECK-LABEL: @cr_clobber
+// CHECK: call void asm sideeffect "", "~{cr}"()
+#[no_mangle]
+pub unsafe fn cr_clobber() {
+    asm!("", out("cr") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @cr0_clobber
+// CHECK: call void asm sideeffect "", "~{cr0}"()
+#[no_mangle]
+pub unsafe fn cr0_clobber() {
+    asm!("", out("cr0") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @cr5_clobber
+// CHECK: call void asm sideeffect "", "~{cr5}"()
+#[no_mangle]
+pub unsafe fn cr5_clobber() {
+    asm!("", out("cr5") _, options(nostack, nomem));
+}
+
+// CHECK-LABEL: @xer_clobber
+// CHECK: call void asm sideeffect "", "~{xer}"()
+#[no_mangle]
+pub unsafe fn xer_clobber() {
+    asm!("", out("xer") _, options(nostack, nomem));
+}
diff --git a/src/test/codegen/uninit-consts-allow-partially-uninit.rs b/src/test/codegen/uninit-consts-allow-partially-uninit.rs
new file mode 100644 (file)
index 0000000..f7420e4
--- /dev/null
@@ -0,0 +1,35 @@
+// compile-flags: -C no-prepopulate-passes -Z partially_uninit_const_threshold=1024
+
+// Like uninit-consts.rs, but tests that we correctly generate partially-uninit consts
+// when the (disabled by default) partially_uninit_const_threshold flag is used.
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+pub struct PartiallyUninit {
+    x: u32,
+    y: MaybeUninit<[u8; 10]>
+}
+
+// This should be partially undef.
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"\EF\BE\AD\DE", [12 x i8] undef }>, align 4
+
+// This shouldn't contain undef, since it's larger than the 1024 byte limit.
+// CHECK: [[UNINIT_PADDING_HUGE:@[0-9]+]] = private unnamed_addr constant <{ [32768 x i8] }> <{ [32768 x i8] c"{{.+}}" }>, align 4
+
+// CHECK-LABEL: @partially_uninit
+#[no_mangle]
+pub const fn partially_uninit() -> PartiallyUninit {
+    const X: PartiallyUninit = PartiallyUninit { x: 0xdeadbeef, y: MaybeUninit::uninit() };
+    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [4 x i8], [12 x i8] }>, <{ [4 x i8], [12 x i8] }>* [[PARTIALLY_UNINIT]], i32 0, i32 0, i32 0), i{{(32|64)}} 16, i1 false)
+    X
+}
+
+// CHECK-LABEL: @uninit_padding_huge
+#[no_mangle]
+pub const fn uninit_padding_huge() -> [(u32, u8); 4096] {
+    const X: [(u32, u8); 4096] = [(123, 45); 4096];
+    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [32768 x i8] }>, <{ [32768 x i8] }>* [[UNINIT_PADDING_HUGE]], i32 0, i32 0, i32 0), i{{(32|64)}} 32768, i1 false)
+    X
+}
diff --git a/src/test/codegen/uninit-consts.rs b/src/test/codegen/uninit-consts.rs
new file mode 100644 (file)
index 0000000..c4c21e0
--- /dev/null
@@ -0,0 +1,40 @@
+// compile-flags: -C no-prepopulate-passes
+
+// Check that we use undef (and not zero) for uninitialized bytes in constants.
+
+#![crate_type = "lib"]
+
+use std::mem::MaybeUninit;
+
+pub struct PartiallyUninit {
+    x: u32,
+    y: MaybeUninit<[u8; 10]>
+}
+
+// CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [16 x i8] }> <{ [16 x i8] c"\EF\BE\AD\DE\00\00\00\00\00\00\00\00\00\00\00\00" }>, align 4
+// CHECK: [[FULLY_UNINIT_HUGE:@[0-9]+]] = private unnamed_addr constant <{ [16384 x i8] }> undef
+
+// CHECK-LABEL: @fully_uninit
+#[no_mangle]
+pub const fn fully_uninit() -> MaybeUninit<[u8; 10]> {
+    const M: MaybeUninit<[u8; 10]> = MaybeUninit::uninit();
+    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 1 %1, i8* align 1 getelementptr inbounds (<{ [10 x i8] }>, <{ [10 x i8] }>* [[FULLY_UNINIT]], i32 0, i32 0, i32 0), i{{(32|64)}} 10, i1 false)
+    M
+}
+
+// CHECK-LABEL: @partially_uninit
+#[no_mangle]
+pub const fn partially_uninit() -> PartiallyUninit {
+    const X: PartiallyUninit = PartiallyUninit { x: 0xdeadbeef, y: MaybeUninit::uninit() };
+    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [16 x i8] }>, <{ [16 x i8] }>* [[PARTIALLY_UNINIT]], i32 0, i32 0, i32 0), i{{(32|64)}} 16, i1 false)
+    X
+}
+
+// CHECK-LABEL: @fully_uninit_huge
+#[no_mangle]
+pub const fn fully_uninit_huge() -> MaybeUninit<[u32; 4096]> {
+    const F: MaybeUninit<[u32; 4096]> = MaybeUninit::uninit();
+    // CHECK: call void @llvm.memcpy.p0i8.p0i8.i{{(32|64)}}(i8* align 4 %1, i8* align 4 getelementptr inbounds (<{ [16384 x i8] }>, <{ [16384 x i8] }>* [[FULLY_UNINIT_HUGE]], i32 0, i32 0, i32 0), i{{(32|64)}} 16384, i1 false)
+    F
+}
index a5d5942b539539861978d420ba2bd61630c7a591..75334558b589d36a0bcec7334dd826e68b369dab 100644 (file)
@@ -1,5 +1,5 @@
 // This test does not passed with gdb < 8.0. See #53497.
-// min-gdb-version: 8.0
+// min-gdb-version: 10.1
 
 // compile-flags:-g
 
index 28ab176ba509acd2a70ec88ea483f86915ba59fb..dec25bb4c203c470729099a4733ce0d227a50790 100644 (file)
@@ -1,5 +1,5 @@
 // Function names are formatted differently in old versions of GDB
-// min-gdb-version: 9.2
+// min-gdb-version: 10.1
 
 // compile-flags:-g
 
@@ -82,8 +82,8 @@
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
-#![feature(const_generics, generators, generator_trait)]
-#![allow(incomplete_features)] // for const_generics
+#![feature(adt_const_params, generators, generator_trait)]
+#![allow(incomplete_features)]
 
 use Mod1::TestTrait2;
 use std::ops::Generator;
diff --git a/src/test/debuginfo/step-into-match.rs b/src/test/debuginfo/step-into-match.rs
new file mode 100644 (file)
index 0000000..4a5f785
--- /dev/null
@@ -0,0 +1,383 @@
+// compile-flags: -g
+// ignore-android: FIXME(#10381)
+
+// === GDB TESTS ==============================================================
+
+// gdb-command: r
+
+// gdb-command: s
+// gdb-check:[...]match x {
+
+// gdb-command: s
+// gdb-check:[...]    Some(42) => 1,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_enum(Some(12));
+
+// gdb-command: s
+// gdb-check:[...]match x {
+
+// gdb-command: s
+// gdb-check:[...]Some(_) => 2,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_enum(None);
+
+// gdb-command: s
+// gdb-check:[...]match x {
+
+// gdb-command: s
+// gdb-check:[...]None => 3,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_int(1);
+
+// gdb-command: s
+// gdb-check:[...]match y {
+
+// gdb-command: s
+// gdb-check:[...]1 => 3,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_int(2);
+
+// gdb-command: s
+// gdb-check:[...]match y {
+
+// gdb-command: s
+// gdb-check:[...]_ => 4,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_int(0);
+
+// gdb-command: s
+// gdb-check:[...]match y {
+
+// gdb-command: s
+// gdb-check:[...]0 => 2,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_int(-1);
+
+// gdb-command: s
+// gdb-check:[...]match y {
+
+// gdb-command: s
+// gdb-check:[...]-1 => 1,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_tuple(5, 12);
+
+// gdb-command: s
+// gdb-check:[...]match (a, b) {
+
+// gdb-command: s
+// gdb-check:[...](5, 12) => 3,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_tuple(29, 1);
+
+// gdb-command: s
+// gdb-check:[...]match (a, b) {
+
+// gdb-command: s
+// gdb-check:[...](29, _) => 2,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_tuple(12, 12);
+
+// gdb-command: s
+// gdb-check:[...]match (a, b) {
+
+// gdb-command: s
+// gdb-check:[...](_, _) => 5
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_tuple(42, 12);
+
+// gdb-command: s
+// gdb-check:[...]match (a, b) {
+
+// gdb-command: s
+// gdb-check:[...](42, 12) => 1,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]match_tuple(1, 9);
+
+// gdb-command: s
+// gdb-check:[...]match (a, b) {
+
+// gdb-command: s
+// gdb-check:[...](_, 9) => 4,
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// gdb-command: s
+// gdb-check:[...]}
+
+// === CDB TESTS ==============================================================
+
+// Enable line-based debugging and print lines after stepping.
+// cdb-command: .lines -e
+// cdb-command: l+s
+// cdb-command: l+t
+
+// cdb-command: g
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_enum(x: Option<u32>) -> u8 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match x {
+
+// cdb-command: t
+// cdb-check:   [...]:         Some(42) => 1,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_enum(Some(12));
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_enum(x: Option<u32>) -> u8 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match x {
+
+// cdb-command: t
+// cdb-check:   [...]:         Some(_) => 2,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_enum(None);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_enum(x: Option<u32>) -> u8 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match x {
+
+// cdb-command: t
+// cdb-check:   [...]:         None => 3,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_int(1);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_int(y: i32) -> u16 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match y {
+
+// cdb-command: t
+// cdb-check:   [...]:         1 => 3,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_int(2);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_int(y: i32) -> u16 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match y {
+
+// cdb-command: t
+// cdb-check:   [...]:         _ => 4,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_int(0);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_int(y: i32) -> u16 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match y {
+
+// cdb-command: t
+// cdb-check:   [...]:         0 => 2,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_int(-1);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_int(y: i32) -> u16 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match y {
+
+// cdb-command: t
+// cdb-check:   [...]:         -1 => 1,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_tuple(5, 12);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_tuple(a: u8, b: i8) -> u32 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match (a, b) {
+
+// cdb-command: t
+// cdb-check:   [...]:         (5, 12) => 3,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_tuple(29, 1);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_tuple(a: u8, b: i8) -> u32 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match (a, b) {
+
+// cdb-command: t
+// cdb-check:   [...]:         (29, _) => 2,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_tuple(12, 12);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_tuple(a: u8, b: i8) -> u32 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match (a, b) {
+
+// cdb-command: t
+// cdb-check:   [...]:         (_, _) => 5
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_tuple(42, 12);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_tuple(a: u8, b: i8) -> u32 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match (a, b) {
+
+// cdb-command: t
+// cdb-check:   [...]:         (42, 12) => 1,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]:     match_tuple(1, 9);
+
+// cdb-command: t
+// cdb-check:   [...]: fn match_tuple(a: u8, b: i8) -> u32 {
+
+// cdb-command: t
+// cdb-check:   [...]:     match (a, b) {
+
+// cdb-command: t
+// cdb-check:   [...]:         (_, 9) => 4,
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+// cdb-command: t
+// cdb-check:   [...]: }
+
+fn main() {
+    match_enum(Some(42)); // #break
+    match_enum(Some(12));
+    match_enum(None);
+
+    match_int(1);
+    match_int(2);
+    match_int(0);
+    match_int(-1);
+
+    match_tuple(5, 12);
+    match_tuple(29, 1);
+    match_tuple(12, 12);
+    match_tuple(42, 12);
+    match_tuple(1, 9);
+}
+
+fn match_enum(x: Option<u32>) -> u8 {
+    match x {
+        Some(42) => 1,
+        Some(_) => 2,
+        None => 3,
+    }
+}
+
+fn match_int(y: i32) -> u16 {
+    match y {
+        -1 => 1,
+        0 => 2,
+        1 => 3,
+        _ => 4,
+    }
+}
+
+fn match_tuple(a: u8, b: i8) -> u32 {
+    match (a, b) {
+        (42, 12) => 1,
+        (29, _) => 2,
+        (5, 12) => 3,
+        (_, 9) => 4,
+        (_, _) => 5
+    }
+}
index f98ae59ddfe3c8b60901e7571f456ac384e9c90a..5ff7b19d8945e635434250ddce7012c63f42e947 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs, adt_const_params)]
 #![allow(incomplete_features)]
 // regression test for #77650
 fn c<T, const N: std::num::NonZeroUsize>()
@@ -9,7 +9,8 @@ fn c<T, const N: std::num::NonZeroUsize>()
     use std::convert::TryFrom;
     <[T; N.get()]>::try_from(())
     //~^ error: the trait bound
-    //~^^ error: mismatched types
+    //~| error: the trait bound
+    //~| error: mismatched types
 }
 
 fn main() {}
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-1.stderr b/src/test/incremental/const-generics/hash-tyvid-regression-1.stderr
deleted file mode 100644 (file)
index cb8ca3a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0277]: the trait bound `[T; _]: From<()>` is not satisfied
-  --> $DIR/hash-tyvid-regression-1.rs:9:5
-   |
-LL |     <[T; N.get()]>::try_from(())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `[T; _]`
-   |
-   = note: required because of the requirements on the impl of `Into<[T; _]>` for `()`
-   = note: required because of the requirements on the impl of `TryFrom<()>` for `[T; _]`
-note: required by `try_from`
-  --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
-   |
-LL |     fn try_from(value: T) -> Result<Self, Self::Error>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0308]: mismatched types
-  --> $DIR/hash-tyvid-regression-1.rs:9:5
-   |
-LL |     <[T; N.get()]>::try_from(())
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found enum `Result`
-   |
-   = note: expected unit type `()`
-                   found enum `Result<[T; _], Infallible>`
-help: consider using a semicolon here
-   |
-LL |     <[T; N.get()]>::try_from(());
-   |                                 +
-help: try adding a return type
-   |
-LL | -> Result<[T; _], Infallible> where
-   | +++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
index 22536ff56d7ce91b8e4ad9a4dcf4c8335a8af310..bba22bf5dc161bd786e4d5f5339ed726d9669a87 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs, adt_const_params, const_generics_defaults)]
 #![allow(incomplete_features)]
 // regression test for #77650
 struct C<T, const N: core::num::NonZeroUsize>([T; N.get()])
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-2.stderr b/src/test/incremental/const-generics/hash-tyvid-regression-2.stderr
deleted file mode 100644 (file)
index 0e6040e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0277]: can't compare `[B; _]` with `&&[A]`
-  --> $DIR/hash-tyvid-regression-2.rs:12:16
-   |
-LL |         self.0 == other
-   |                ^^ no implementation for `[B; _] == &&[A]`
-   |
-   = help: the trait `PartialEq<&&[A]>` is not implemented for `[B; _]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index 76b1ae11c7d039c9bf0d2b34fcf904b993db0192..61f568f79ef92419a3428cbc1be3f7ef0e55efb9 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 // regression test for #79251
 struct Node<const D: usize>
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-3.stderr b/src/test/incremental/const-generics/hash-tyvid-regression-3.stderr
deleted file mode 100644 (file)
index 555d467..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `some_function` found for struct `SmallVec` in the current scope
-  --> $DIR/hash-tyvid-regression-3.rs:17:19
-   |
-LL |         node.keys.some_function();
-   |                   ^^^^^^^^^^^^^ method not found in `SmallVec<{ D * 2 }>`
-...
-LL | struct SmallVec<const D: usize> {}
-   | ------------------------------- method `some_function` not found for this
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
index 35a675a2ab4d26ce7a7a3cf77147ef176d8f5444..12e8ac7abadc0b4640dcac9f9eaa9020f7e11e85 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 // regression test for #79251
 #[derive(Debug)]
diff --git a/src/test/incremental/const-generics/hash-tyvid-regression-4.stderr b/src/test/incremental/const-generics/hash-tyvid-regression-4.stderr
deleted file mode 100644 (file)
index c9a6715..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0599]: no method named `push` found for struct `SmallVec` in the current scope
-  --> $DIR/hash-tyvid-regression-4.rs:23:19
-   |
-LL |         node.keys.push(k);
-   |                   ^^^^ method not found in `SmallVec<_, { D * 2 }>`
-...
-LL | struct SmallVec<T, const D: usize> {
-   | ---------------------------------- method `push` not found for this
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
index 00b3b29698bed85cb66f2eb7115eff3c82dcbbd7..e9d67fee2969af65c0bb55db1f6046ed0780b8ac 100644 (file)
@@ -1,7 +1,5 @@
 // revisions:rpass1
 
-#![feature(const_generics)]
-
 struct Struct<T>(T);
 
 impl<T, const N: usize> Struct<[T; N]> {
index a193bf998dc73e5104b8aa3358ba2452fa6b2fb3..c781484d1e2e97b0520c3c9b66f688763cbf97a1 100644 (file)
@@ -1,7 +1,5 @@
 // revisions:rpass1
 
-#![feature(const_generics)]
-
 struct FakeArray<T, const N: usize>(T);
 
 impl<T, const N: usize> FakeArray<T, N> {
index 0eaeb910be64a591cbe078a40d000fc8e2fb039a..93c1dbf44e93839b87ec0a1416766d0df79aa5a4 100644 (file)
@@ -1,7 +1,4 @@
 // revisions:cfail1
-#![feature(const_generics)]
-//[cfail1]~^ WARN the feature `const_generics` is incomplete
-
 struct S<T, const N: usize>([T; N]);
 
 fn f<T, const N: usize>(x: T) -> S<T, {N}> { panic!() }
index 6b10c5404944d743beea80c609c93a775e8722c7..81c813531bd53d6bd6b09ff164d466e3cb2f31cb 100644 (file)
@@ -1,6 +1,4 @@
 // revisions:cfail1
-#![feature(const_generics)]
-//[cfail1]~^ WARN the feature `const_generics` is incomplete
 
 fn combinator<T, const S: usize>() -> [T; S] {}
 //[cfail1]~^ ERROR mismatched types
index 353e323e67b448dad05424b299d9c7aa9a456fcd..22bbcbcabed1b7c8363db1dac4f96b89ba034702 100644 (file)
@@ -1,6 +1,4 @@
 // revisions:rpass1
-#![feature(const_generics)]
-
 pub struct Foo<T, const N: usize>([T; 0]);
 
 impl<T, const N: usize> Foo<T, {N}> {
index 925931bc4a635b80fc1848b27a1c93d8d5f25b80..9e35cf93d0911845c670c50acab1cf6f59f6d57e 100644 (file)
@@ -1,6 +1,8 @@
 // edition:2018
 // revisions:rpass1
-#![feature(const_generics)]
+
+// Needed to supply generic arguments to the anon const in `[(); FOO]`.
+#![feature(generic_const_exprs)]
 
 const FOO: usize = 1;
 
index a6edbb2e9f9968943d9127956bac8eee8523a5b7..8262a2a211b7ede1d8cd6f00bbfb9c865564a92f 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features, unused_braces)]
 
 trait Delegates<T> {}
index 52eeec73b0dd385541095d77849ba467fca01ec0..92bbcba4b38ac94f29371524a8e644007e512b7f 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 struct Z;
index 11cca942dd639a9bc3f0e85aa27e09628a395608..fc114f224a2fad1410450e414e4973d6714b1b32 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs, adt_const_params)]
 #![allow(incomplete_features)]
 
 use std::{convert::TryFrom, num::NonZeroUsize};
index 1b769d0a30dced547c29e789a7ab606a21b8f45d..c05d8355c280d7fa94539c2e028da0e71e904583 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 pub trait IsTrue {}
 pub trait IsFalse {}
index 20d4993774de35a3c3b7231794513dab15259cbd..8886a556dbb25f06f364b7ee4a8d6ac305c43eba 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 pub struct Ref<'a, const NUM: usize>(&'a i32);
index be7ad6d1fa0316e9ed7616f1334fa9eed315055f..db1e2fc2af481168116ecd4981656cca8211b3b6 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: cfail
 #![allow(incomplete_features)]
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 
 pub struct Ref<'a>(&'a i32);
 
index af4f209c9045838365f7d465b7fa5dab62f19840..5b2f5edc8500e8f9b1e02fd7be3f92c15f0bf404 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 fn test<const SIZE: usize>() {}
index ba8633696263353a7bddaf9d5c212bce89d6c9af..d659c5676336e51387d88311c0fc4a1809d6270c 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: rpass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 struct Foo;
index da713631cc1fc998ff0e6016d0caa33768475064..5f5435ba9f289f81d15f4be68db007ce461dee57 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: cfail
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features, unused_braces)]
 
 struct Buffer<T, const S: usize>
index 28b8329606c1bcc7fede011e9bb78322b3d5689b..1969d5e0404092ca5369967f9e2d6e28d8d8a28f 100644 (file)
@@ -7,18 +7,18 @@
       let mut _2: isize;                   // in scope 0 at $DIR/76803_regression.rs:12:9: 12:16
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/76803_regression.rs:12:9: 12:16
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:12:9: 12:16
+          _2 = discriminant(_1);           // scope 0 at $DIR/76803_regression.rs:11:11: 11:12
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:11:5: 11:12
       }
   
       bb1: {
           _0 = move _1;                    // scope 0 at $DIR/76803_regression.rs:13:14: 13:15
-          goto -> bb3;                     // scope 0 at $DIR/76803_regression.rs:11:5: 14:6
+          goto -> bb3;                     // scope 0 at $DIR/76803_regression.rs:13:14: 13:15
       }
   
       bb2: {
           discriminant(_0) = 1;            // scope 0 at $DIR/76803_regression.rs:12:20: 12:27
-          goto -> bb3;                     // scope 0 at $DIR/76803_regression.rs:11:5: 14:6
+          goto -> bb3;                     // scope 0 at $DIR/76803_regression.rs:12:20: 12:27
       }
   
       bb3: {
index a14f64467a643b50da9ceb862f35844b0d70de53..8f57d307abf5872f2675f5343660fe59a7a5b927 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const true);    // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:3:16: 3:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
       }
   
       bb1: {
index 4e9c255ad6265db607ae7e8e6961000eaf2cf8d1..1f5738ae7583737475c7e8739210953870748d07 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(const true, move _3);    // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
       }
   
       bb1: {
index 2048c97a9e1c3b3d21fca66062677f6183008f9c..3320509a7b37aa3320c034648e4378194f896892 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const false);   // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:13:17: 13:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
       }
   
       bb1: {
index efcaa2766a9ed831f04aba7b1521db0c07b4c3a6..02049f4126da5b44245007cbb3267914a60ff2cf 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(const false, move _3);   // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
       }
   
       bb1: {
index ddb9a8034e8bfc60a7c5bbe51433a3e0d6b58c09..544d16a251a82586fa83074d57f7b60b31739eea 100644 (file)
   
       bb0: {
 -         StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
--         _3 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:12:22: 12:28
--         switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto.rs:12:22: 12:28
-+         _2 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:12:22: 12:28
-+         switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto.rs:12:22: 12:28
+-         _3 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:12:17: 12:20
+-         switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _2 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:12:17: 12:20
++         switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
@@ -29,7 +29,7 @@
 -     }
 - 
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto.rs:12:5: 12:57
+-         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb4: {
index f0103fc42025a6a856dfc23f4ef177e1abb1d4cc..9ba02942b58b6af4d9159e7cc6ce6075623a3012 100644 (file)
           StorageLive(_1);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:11: 12:6
           StorageLive(_2);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:8:15: 8:16
           _2 = const A;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:8:15: 8:16
-          switchInt(_2) -> [1_i32: bb2, 2_i32: bb2, 3_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:9:13: 9:14
+          switchInt(_2) -> [1_i32: bb2, 2_i32: bb2, 3_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:8:9: 8:16
       }
   
       bb1: {
           _1 = const true;                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:10:18: 10:22
-          goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:8:9: 11:10
+          goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:10:18: 10:22
       }
   
       bb2: {
           _1 = const B;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:9:26: 9:27
--         goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:8:9: 11:10
-+         switchInt(_1) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:13:9: 13:14
+-         goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:9:26: 9:27
++         switchInt(_1) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 12:6
       }
   
       bb3: {
--         switchInt(_1) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:13:9: 13:14
+-         switchInt(_1) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 12:6
 -     }
 - 
 -     bb4: {
           _0 = const 2_u64;                // scope 0 at $DIR/const_goto_const_eval_fail.rs:14:17: 14:18
--         goto -> bb6;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 15:6
-+         goto -> bb5;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 15:6
+-         goto -> bb6;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:14:17: 14:18
++         goto -> bb5;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:14:17: 14:18
       }
   
 -     bb5: {
 +     bb4: {
           _0 = const 1_u64;                // scope 0 at $DIR/const_goto_const_eval_fail.rs:13:18: 13:19
--         goto -> bb6;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 15:6
-+         goto -> bb5;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:7:5: 15:6
+-         goto -> bb6;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:13:18: 13:19
++         goto -> bb5;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:13:18: 13:19
       }
   
 -     bb6: {
index 6f4bd65b85d4d784f210dd403aa89eeeb11e6ffa..49d0a7ff455030181b4c27bd926b51ad958f675d 100644 (file)
@@ -30,7 +30,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 +                                          // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
index 8c9a37bce854ba8c2db12d7066e2c8ed4054f128..f2504ae880eab2944f991db4ba81cfe0542cc458 100644 (file)
@@ -32,7 +32,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 +                                          // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
index db6e1369161fb37d03a8fef90d6da5c5587b955c..f8fd2cc9b0d084b9dda42c28314702d7442ae208 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index db6e1369161fb37d03a8fef90d6da5c5587b955c..f8fd2cc9b0d084b9dda42c28314702d7442ae208 100644 (file)
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
index d7bc035e667afdb2ae7fba27c04147c02b33883d..49237934223e765d351295161846409d2c9c9af0 100644 (file)
@@ -22,7 +22,7 @@
                                            // + val: Unevaluated(FOO, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs_: Some([]), promoted: None }) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
           _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
index 1b7c51b395484b6e41cb4b7fc5e3912fd2302913..1eb40e50d7aa00dc07e2dabd4d1b52de1269f754 100644 (file)
@@ -9,9 +9,9 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
 -         _1 = const <bool as NeedsDrop>::NEEDS; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
--         switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
+-         switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
 +         _1 = const false;                // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
-+         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:5: 14:6
++         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control-flow-simplification.rs:12:8: 12:21
       }
   
       bb1: {
index 706cd63a73f6aa86ebf2c67eca383772e6d339a6..de23e5446a0229119b8f7912624e3741cf99f057 100644 (file)
           ((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
           discriminant(_3) = 1;            // scope 0 at $DIR/discriminant.rs:11:34: 11:44
 -         _4 = discriminant(_3);           // scope 0 at $DIR/discriminant.rs:11:21: 11:31
--         switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
+-         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
 +         _4 = const 1_isize;              // scope 0 at $DIR/discriminant.rs:11:21: 11:31
-+         switchInt(const 1_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
++         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
       }
   
       bb1: {
-          _2 = const 10_i32;               // scope 0 at $DIR/discriminant.rs:11:59: 11:61
-          goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
+          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
+          _2 = const 42_i32;               // scope 0 at $DIR/discriminant.rs:11:47: 11:49
+          goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
       }
   
       bb3: {
-          _2 = const 42_i32;               // scope 0 at $DIR/discriminant.rs:11:47: 11:49
+          _2 = const 10_i32;               // scope 0 at $DIR/discriminant.rs:11:59: 11:61
           goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
       }
   
index 706cd63a73f6aa86ebf2c67eca383772e6d339a6..de23e5446a0229119b8f7912624e3741cf99f057 100644 (file)
           ((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
           discriminant(_3) = 1;            // scope 0 at $DIR/discriminant.rs:11:34: 11:44
 -         _4 = discriminant(_3);           // scope 0 at $DIR/discriminant.rs:11:21: 11:31
--         switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
+-         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
 +         _4 = const 1_isize;              // scope 0 at $DIR/discriminant.rs:11:21: 11:31
-+         switchInt(const 1_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
++         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
       }
   
       bb1: {
-          _2 = const 10_i32;               // scope 0 at $DIR/discriminant.rs:11:59: 11:61
-          goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
+          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30
+          _2 = const 42_i32;               // scope 0 at $DIR/discriminant.rs:11:47: 11:49
+          goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
       }
   
       bb3: {
-          _2 = const 42_i32;               // scope 0 at $DIR/discriminant.rs:11:47: 11:49
+          _2 = const 10_i32;               // scope 0 at $DIR/discriminant.rs:11:59: 11:61
           goto -> bb4;                     // scope 0 at $DIR/discriminant.rs:11:13: 11:64
       }
   
index 4e19465189c933ec742b116bc3ef9196ce8c66b5..54acae43abc58ae1630b3205882ef8808ab77236 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 +         _1 = const 4_i32;                // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
index a58dabdaa4159cd9192750930507461858e7398e..3b5c86942a7511b037525010df8ca2c3a360d03d 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
-+                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
index bb265b2af7d30150fe9245400ab6917af9941d6c..8590a98491b7be8aea83fe6b8e239b02cf91ba9a 100644 (file)
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
           StorageDead(_2);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index bb7570fabbba8e02c0ac6cc37472f13b60d346df..4e10ae17934881b5e242b4f72e6ddd38079e8e94 100644 (file)
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
index d5a36182e35017536045d3efd24fc1c23081c8ca..f305d602bbde106c4acdcba8a5379236cbe57b17 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index d5a36182e35017536045d3efd24fc1c23081c8ca..f305d602bbde106c4acdcba8a5379236cbe57b17 100644 (file)
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
index f51df7ae821ce35548135ee92af48cd81e6c7248..f031a703a9d728a482b9ea854714ed481a0b4b3d 100644 (file)
@@ -8,8 +8,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:7:11: 7:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:7:11: 7:12
--         switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:8:9: 8:10
-+         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:8:9: 8:10
+-         switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:7:5: 7:12
++         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:7:5: 7:12
       }
   
       bb1: {
index a444956ad1d0a8dd1a4e765c741e6f94e83dbf3d..6a5b88c4a7f0d11a61cbedc24fb99928ec0c0429 100644 (file)
@@ -8,8 +8,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:7:11: 7:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:7:11: 7:12
--         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:8:9: 8:10
-+         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:8:9: 8:10
+-         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:7:5: 7:12
++         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:7:5: 7:12
       }
   
       bb1: {
index 6d2dbb820f9621212b3d59ccbf098f8baae79a34..629bed8fec5d4e500ca52ac4295019a954a4c3fd 100644 (file)
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:8: 10:9
           _3 = _1;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:8: 10:9
-          switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:5: 14:6
+          switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:10:8: 10:9
       }
   
       bb1: {
index b0c97f423781876ac0ffe0d6264494400fecd6f4..48a37a8496cb720ae8a842ee0dafa0a10f649d10 100644 (file)
       }
   
       bb1: {
-          switchInt((*_2)[0 of 4]) -> [47_u8: bb2, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:4:10: 4:14
+          switchInt((*_2)[0 of 4]) -> [47_u8: bb2, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb2: {
-          switchInt((*_2)[1 of 4]) -> [47_u8: bb3, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:4:16: 4:20
+          switchInt((*_2)[1 of 4]) -> [47_u8: bb3, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb3: {
-          switchInt((*_2)[2 of 4]) -> [47_u8: bb4, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:4:22: 4:26
+          switchInt((*_2)[2 of 4]) -> [47_u8: bb4, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb4: {
--         switchInt((*_2)[3 of 4]) -> [47_u8: bb10, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:4:28: 4:32
-+         switchInt((*_2)[3 of 4]) -> [47_u8: bb9, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:4:28: 4:32
+-         switchInt((*_2)[3 of 4]) -> [47_u8: bb10, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
++         switchInt((*_2)[3 of 4]) -> [47_u8: bb9, otherwise: bb5]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb5: {
       }
   
       bb6: {
-          switchInt((*_2)[0 of 3]) -> [47_u8: bb7, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:5:10: 5:14
+          switchInt((*_2)[0 of 3]) -> [47_u8: bb7, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb7: {
-          switchInt((*_2)[1 of 3]) -> [47_u8: bb8, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:5:16: 5:20
+          switchInt((*_2)[1 of 3]) -> [47_u8: bb8, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb8: {
--         switchInt((*_2)[2 of 3]) -> [47_u8: bb11, 33_u8: bb12, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:5:22: 5:26
-+         switchInt((*_2)[2 of 3]) -> [47_u8: bb10, 33_u8: bb10, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:5:22: 5:26
+-         switchInt((*_2)[2 of 3]) -> [47_u8: bb11, 33_u8: bb12, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
++         switchInt((*_2)[2 of 3]) -> [47_u8: bb10, 33_u8: bb10, otherwise: bb9]; // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 3:23
       }
   
       bb9: {
 -         _0 = const false;                // scope 0 at $DIR/deduplicate_blocks.rs:7:14: 7:19
--         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
+-         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:7:14: 7:19
 -     }
 - 
 -     bb10: {
           _0 = const false;                // scope 0 at $DIR/deduplicate_blocks.rs:4:41: 4:46
--         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
-+         goto -> bb11;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
+-         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:4:41: 4:46
++         goto -> bb11;                    // scope 0 at $DIR/deduplicate_blocks.rs:4:41: 4:46
       }
   
 -     bb11: {
 -         _0 = const true;                 // scope 0 at $DIR/deduplicate_blocks.rs:5:35: 5:39
--         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
+-         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:5:35: 5:39
 -     }
 - 
 -     bb12: {
 +     bb10: {
           _0 = const true;                 // scope 0 at $DIR/deduplicate_blocks.rs:6:35: 6:39
--         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
-+         goto -> bb11;                    // scope 0 at $DIR/deduplicate_blocks.rs:3:5: 8:6
+-         goto -> bb13;                    // scope 0 at $DIR/deduplicate_blocks.rs:6:35: 6:39
++         goto -> bb11;                    // scope 0 at $DIR/deduplicate_blocks.rs:6:35: 6:39
       }
   
 -     bb13: {
index 500d6d20db8932ee9b37f729a939e15d71ad80dd..02821a1079e0a219bc25e670e856f3ee8927138a 100644 (file)
@@ -36,7 +36,7 @@
       }
   
       bb2: {
-          switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:15:13: 20:6
+          switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:15:16: 15:22
       }
   
       bb3: {
index 386726bfddc74676c302be2c9adcb203702664ac..c1591e5d72915c0bf6435b60e8d057ead34b09ff 100644 (file)
           (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:4:11: 4:17
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:4:16: 4:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:4:16: 4:17
-          _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
--         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         _10 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         _11 = Ne(_10, _7);               // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
-+         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:10: 5:17
+          _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:4:11: 4:17
+-         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         _10 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         _11 = Ne(_10, _7);               // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
++         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
       }
   
       bb1: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
           _0 = const 1_u32;                // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
--         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
-+         goto -> bb3;                     // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
+-         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
++         goto -> bb3;                     // scope 0 at $DIR/early_otherwise_branch.rs:6:14: 6:15
       }
   
       bb2: {
--         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
--         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:5:19: 5:26
+-         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:4:11: 4:17
+-         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 4:17
 -     }
 - 
 -     bb3: {
@@ -59,8 +59,8 @@
           _0 = const 0_u32;                // scope 1 at $DIR/early_otherwise_branch.rs:5:31: 5:32
           StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
           StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
--         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
-+         goto -> bb3;                     // scope 0 at $DIR/early_otherwise_branch.rs:4:5: 7:6
+-         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
++         goto -> bb3;                     // scope 0 at $DIR/early_otherwise_branch.rs:5:31: 5:32
       }
   
 -     bb4: {
index bc5934dec84e41961e0e4ed888b6a28e888175e8..b949d307e20e9c2bce600e3e770e41bff376e4d6 100644 (file)
           (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17
-          _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
--         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         _12 = Ne(_11, _8);               // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
-+         switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:13:10: 13:17
+          _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
+-         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         _12 = Ne(_11, _8);               // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
++         switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
       }
   
       bb1: {
--         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
--         switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:14:16: 14:20
+-         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
+-         switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 -     }
 - 
 -     bb2: {
 +         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
           _0 = const 1_u32;                // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
--         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
-+         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
+-         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
++         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15
       }
   
 -     bb3: {
--         _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:13:19: 13:26
--         switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:13:19: 13:26
+-         _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17
+-         switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17
 -     }
 - 
 -     bb4: {
           _0 = const 0_u32;                // scope 1 at $DIR/early_otherwise_branch.rs:13:31: 13:32
           StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
           StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
--         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
-+         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
+-         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
++         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:13:31: 13:32
       }
   
 -     bb5: {
 +     bb3: {
           _0 = const 0_u32;                // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
--         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
-+         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 16:6
+-         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
++         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch.rs:14:25: 14:26
       }
   
 -     bb6: {
index b0357f1aecd61f7cf5f42f582a3403fbb81de9f2..5b9ec1e53d946a1810799d7350111c5cb9119ed8 100644 (file)
           StorageDead(_7);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:19: 5:20
           StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:19: 5:20
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:19: 5:20
-          _10 = discriminant((_4.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
--         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         _14 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         _15 = Ne(_14, _10);              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
-+         switchInt(move _15) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:10: 6:17
+          _10 = discriminant((_4.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:11: 5:20
+-         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         _14 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         _15 = Ne(_14, _10);              // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         switchInt(move _15) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
       }
   
       bb1: {
 +         StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:14: 7:15
 +         StorageDead(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:14: 7:15
           _0 = const 1_u32;                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:14: 7:15
--         goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
-+         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
+-         goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:14: 7:15
++         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:7:14: 7:15
       }
   
       bb2: {
--         _9 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:19: 6:26
--         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:19: 6:26
+-         _9 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:11: 5:20
+-         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
 -     }
 - 
 -     bb3: {
-          _8 = discriminant((_4.2: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:28: 6:35
--         switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:28: 6:35
-+         switchInt(move _8) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:28: 6:35
+          _8 = discriminant((_4.2: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:11: 5:20
+-         switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
++         switchInt(move _8) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 5:20
       }
   
 -     bb4: {
@@ -81,8 +81,8 @@
           StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
           StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
           StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
--         goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
-+         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:5:5: 8:6
+-         goto -> bb5;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
++         goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:6:40: 6:41
       }
   
 -     bb5: {
index 2893ee9ac334b1b1d771fabb22642d87012d4e49..f23d035545eec8533eac2b4f403cf1a3d4ebde60 100644 (file)
           StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
 -         StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
-          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
--         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
+          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
       }
   
       bb1: {
--         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
--         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
+-         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 -     }
 - 
 -     bb2: {
 +         nop;                             // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 +     }
 + 
       bb3: {
--         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
--         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
+-         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
 +         _20 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29
 +         nop;                             // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
       }
   
       bb4: {
--         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
--         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
+-         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
 +         _25 = (((*(_4.0: &ViewportPercentageLength)) as Vmin).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:16: 24:19
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:28: 24:33
 +         nop;                             // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
       }
   
       bb5: {
--         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
--         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
+-         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
 +         _30 = (((*(_4.0: &ViewportPercentageLength)) as Vmax).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:16: 25:19
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:28: 25:33
 +         nop;                             // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
       }
   
       bb6: {
 -         StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 -         StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 -         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
 +         discriminant(_0) = 0;            // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7
 +         nop;                             // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7
 -         StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
 -         StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
 -         StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
 -     }
 - 
 -     bb8: {
 -         StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
 -         StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
 -         StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
 -     }
 - 
 -     bb9: {
 -         StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
 -         StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
 -         StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
 -     }
 - 
 -     bb10: {
index 9039989e0f288e72fd633dea136de423b77d1615..af32d4d2d149cb90db1ebed63a64782b15e35516 100644 (file)
           (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
           StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24
-          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
--         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
-+         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:11: 22:18
+          _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageLive(_35);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         _35 = Ne(_34, _11);              // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         StorageDead(_34);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
++         switchInt(move _35) -> [false: bb7, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
       }
   
       bb1: {
--         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
--         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:21: 22:30
+-         _7 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 -     }
 - 
 -     bb2: {
       }
   
 -     bb3: {
--         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
--         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:21: 23:30
+-         _8 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 -     }
 - 
 -     bb4: {
--         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
--         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:23: 24:34
+-         _9 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 -     }
 - 
 -     bb5: {
--         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
--         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:23: 25:34
+-         _10 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24
+-         switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24
 -     }
 - 
 -     bb6: {
           StorageDead(_14);                // scope 1 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
           StorageDead(_13);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
           StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50
       }
   
 -     bb7: {
           StorageDead(_19);                // scope 2 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
           StorageDead(_18);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
           StorageDead(_17);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:49: 23:50
       }
   
 -     bb8: {
           StorageDead(_24);                // scope 3 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
           StorageDead(_23);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
           StorageDead(_22);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:24:55: 24:56
       }
   
 -     bb9: {
           StorageDead(_29);                // scope 4 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
           StorageDead(_28);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
           StorageDead(_27);                // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
--         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
-+         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 27:6
+-         goto -> bb10;                    // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
++         goto -> bb6;                     // scope 0 at $DIR/early_otherwise_branch_68867.rs:25:55: 25:56
       }
   
 -     bb10: {
index 9a6094f12dfb164dd4fb6022cae9c417bd744c67..5343f22d3da3e427a11f6c38389ff2c6438bca92 100644 (file)
           (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:16: 8:17
-          _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:10: 9:17
-          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:10: 9:17
+          _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
+          switchInt(move _8) -> [0_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
       }
   
       bb1: {
-          _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:16: 11:23
-          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:16: 11:23
+          _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
+          switchInt(move _6) -> [0_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
       }
   
       bb2: {
           _0 = const 3_u32;                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 13:6
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:12:25: 12:26
       }
   
       bb3: {
-          _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:19: 9:26
-          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:19: 9:26
+          _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:11: 8:17
+          switchInt(move _7) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 8:17
       }
   
       bb4: {
@@ -63,7 +63,7 @@
           _0 = const 0_u32;                // scope 1 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
           StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
           StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 13:6
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:9:31: 9:32
       }
   
       bb5: {
@@ -71,7 +71,7 @@
           _11 = (((_3.0: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:15: 10:16
           _0 = const 1_u32;                // scope 2 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
           StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 13:6
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:10:28: 10:29
       }
   
       bb6: {
@@ -79,7 +79,7 @@
           _12 = (((_3.1: std::option::Option<u32>) as Some).0: u32); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:21: 11:22
           _0 = const 2_u32;                // scope 3 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
           StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
-          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:8:5: 13:6
+          goto -> bb7;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:11:28: 11:29
       }
   
       bb7: {
index c3aecb4529351f5d66b072c399274e33af8fca64..66ea828bf682c422077200f86e3e2efdf0abeffa 100644 (file)
           (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:16: 19:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:16: 19:17
-          _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:10: 20:17
-          switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:10: 20:17
+          _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17
+          switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 19:17
       }
   
       bb1: {
           _0 = const 1_u32;                // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:14: 21:15
-          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 22:6
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:21:14: 21:15
       }
   
       bb2: {
-          _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:19: 20:26
-          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:19: 20:26
+          _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:11: 19:17
+          switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 19:17
       }
   
       bb3: {
@@ -49,7 +49,7 @@
           _0 = const 0_u32;                // scope 1 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32
           StorageDead(_9);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32
           StorageDead(_8);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32
-          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:19:5: 22:6
+          goto -> bb4;                     // scope 0 at $DIR/early_otherwise_branch_noopt.rs:20:31: 20:32
       }
   
       bb4: {
index 1bc4c0f8b37e3c1e54ab51a42d205c7a8e4e53f9..174095888b48a4e8290934fa21bebf3fb29ce644 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const true);    // scope 0 at $DIR/equal_true.rs:4:8: 4:17
 +         _2 = move _3;                    // scope 0 at $DIR/equal_true.rs:4:8: 4:17
           StorageDead(_3);                 // scope 0 at $DIR/equal_true.rs:4:16: 4:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:4:5: 4:34
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:4:8: 4:17
       }
   
       bb1: {
index 93507879a6f83e286563fb152ae91c6215301369..6b7b3db05419e764157e26267d95523ed66b67c9 100644 (file)
@@ -19,21 +19,21 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential-or.rs:5:11: 5:12
-        switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:15: 6:16
+        switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:15: 6:20
     }
 
     bb1: {
         _0 = const 0_u32;                // scope 0 at $DIR/exponential-or.rs:7:14: 7:15
-        goto -> bb10;                    // scope 0 at $DIR/exponential-or.rs:5:5: 8:6
+        goto -> bb10;                    // scope 0 at $DIR/exponential-or.rs:7:14: 7:15
     }
 
     bb2: {
-        _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential-or.rs:6:37: 6:48
-        switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:37: 6:48
+        _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential-or.rs:6:37: 6:55
+        switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:37: 6:55
     }
 
     bb3: {
-        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:42: 6:43
+        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential-or.rs:6:37: 6:55
     }
 
     bb4: {
@@ -74,7 +74,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
         StorageDead(_9);                 // scope 1 at $DIR/exponential-or.rs:6:87: 6:88
         StorageDead(_8);                 // scope 0 at $DIR/exponential-or.rs:6:87: 6:88
         StorageDead(_7);                 // scope 0 at $DIR/exponential-or.rs:6:87: 6:88
-        goto -> bb10;                    // scope 0 at $DIR/exponential-or.rs:5:5: 8:6
+        goto -> bb10;                    // scope 0 at $DIR/exponential-or.rs:6:87: 6:88
     }
 
     bb10: {
index a7e4a131bfb729224c59522a8d216b7ee24c1a2b..fd29e14a04161bcd01daa38ed6377377c7278baf 100644 (file)
       bb1: {
           StorageDead(_5);                 // scope 0 at $DIR/funky_arms.rs:15:36: 15:37
           StorageLive(_6);                 // scope 1 at $DIR/funky_arms.rs:19:9: 19:13
-          switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:20:9: 20:14
+          switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:19:16: 19:32
       }
   
       bb2: {
           discriminant(_6) = 1;            // scope 1 at $DIR/funky_arms.rs:21:17: 21:41
-          goto -> bb4;                     // scope 1 at $DIR/funky_arms.rs:19:16: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/funky_arms.rs:21:17: 21:41
       }
   
       bb3: {
           discriminant(_6) = 0;            // scope 1 at $DIR/funky_arms.rs:20:18: 20:38
-          goto -> bb4;                     // scope 1 at $DIR/funky_arms.rs:19:16: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/funky_arms.rs:20:18: 20:38
       }
   
       bb4: {
       bb5: {
           StorageDead(_8);                 // scope 2 at $DIR/funky_arms.rs:24:44: 24:45
           _9 = discriminant(_7);           // scope 2 at $DIR/funky_arms.rs:24:12: 24:27
-          switchInt(move _9) -> [1_isize: bb7, otherwise: bb6]; // scope 2 at $DIR/funky_arms.rs:24:12: 24:27
+          switchInt(move _9) -> [1_isize: bb6, otherwise: bb8]; // scope 2 at $DIR/funky_arms.rs:24:12: 24:27
       }
   
       bb6: {
-          StorageLive(_18);                // scope 2 at $DIR/funky_arms.rs:28:46: 28:49
-          _18 = &mut (*_1);                // scope 2 at $DIR/funky_arms.rs:28:46: 28:49
-          StorageLive(_19);                // scope 2 at $DIR/funky_arms.rs:28:51: 28:54
-          _19 = _2;                        // scope 2 at $DIR/funky_arms.rs:28:51: 28:54
-          StorageLive(_20);                // scope 2 at $DIR/funky_arms.rs:28:56: 28:60
-          _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:28:56: 28:60
-          StorageLive(_21);                // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
-          _21 = _3;                        // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
-          _0 = float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:28:9: 28:68
-                                           // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:28:9: 28:45
-                                           // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(Scalar(<ZST>)) }
-      }
-  
-      bb7: {
           StorageLive(_10);                // scope 2 at $DIR/funky_arms.rs:24:17: 24:26
           _10 = ((_7 as Some).0: usize);   // scope 2 at $DIR/funky_arms.rs:24:17: 24:26
           StorageLive(_11);                // scope 2 at $DIR/funky_arms.rs:26:43: 26:46
           StorageDead(_15);                // scope 2 at $DIR/funky_arms.rs:26:78: 26:79
           StorageLive(_17);                // scope 2 at $DIR/funky_arms.rs:26:81: 26:86
           _17 = _3;                        // scope 2 at $DIR/funky_arms.rs:26:81: 26:86
-          _0 = float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb8; // scope 2 at $DIR/funky_arms.rs:26:9: 26:87
+          _0 = float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 2 at $DIR/funky_arms.rs:26:9: 26:87
                                            // mir::Constant
                                            // + span: $DIR/funky_arms.rs:26:9: 26:42
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, u32, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(Scalar(<ZST>)) }
       }
   
-      bb8: {
+      bb7: {
           StorageDead(_17);                // scope 2 at $DIR/funky_arms.rs:26:86: 26:87
           StorageDead(_14);                // scope 2 at $DIR/funky_arms.rs:26:86: 26:87
           StorageDead(_13);                // scope 2 at $DIR/funky_arms.rs:26:86: 26:87
           StorageDead(_12);                // scope 2 at $DIR/funky_arms.rs:26:86: 26:87
           StorageDead(_11);                // scope 2 at $DIR/funky_arms.rs:26:86: 26:87
+          StorageDead(_10);                // scope 2 at $DIR/funky_arms.rs:27:5: 27:6
           goto -> bb10;                    // scope 2 at $DIR/funky_arms.rs:24:5: 29:6
       }
   
+      bb8: {
+          StorageLive(_18);                // scope 2 at $DIR/funky_arms.rs:28:46: 28:49
+          _18 = &mut (*_1);                // scope 2 at $DIR/funky_arms.rs:28:46: 28:49
+          StorageLive(_19);                // scope 2 at $DIR/funky_arms.rs:28:51: 28:54
+          _19 = _2;                        // scope 2 at $DIR/funky_arms.rs:28:51: 28:54
+          StorageLive(_20);                // scope 2 at $DIR/funky_arms.rs:28:56: 28:60
+          _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:28:56: 28:60
+          StorageLive(_21);                // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
+          _21 = _3;                        // scope 2 at $DIR/funky_arms.rs:28:62: 28:67
+          _0 = float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:28:9: 28:68
+                                           // mir::Constant
+                                           // + span: $DIR/funky_arms.rs:28:9: 28:45
+                                           // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(Scalar(<ZST>)) }
+      }
+  
       bb9: {
           StorageDead(_21);                // scope 2 at $DIR/funky_arms.rs:28:67: 28:68
           StorageDead(_20);                // scope 2 at $DIR/funky_arms.rs:28:67: 28:68
       }
   
       bb10: {
-          StorageDead(_10);                // scope 2 at $DIR/funky_arms.rs:29:5: 29:6
           StorageDead(_6);                 // scope 1 at $DIR/funky_arms.rs:30:1: 30:2
           StorageDead(_4);                 // scope 0 at $DIR/funky_arms.rs:30:1: 30:2
           StorageDead(_7);                 // scope 0 at $DIR/funky_arms.rs:30:1: 30:2
index 875e5a0a71f336272d4dbe4512503c005328d319..dddb7acae2b2c21c7bf8e4479051b1700b043f6f 100644 (file)
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/if-condition-int.rs:17:8: 17:9
           _2 = _1;                         // scope 0 at $DIR/if-condition-int.rs:17:8: 17:9
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:17:5: 17:26
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:17:8: 17:9
       }
   
       bb1: {
index 64a3f52f3a06ac870b750c0353c90de61e916db4..2ff8386b205bd024894f9bfe903e0b4712ede733 100644 (file)
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:53:8: 53:9
           _2 = Eq(move _3, const -42f32);  // scope 0 at $DIR/if-condition-int.rs:53:8: 53:18
           StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:53:17: 53:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:53:5: 53:35
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:53:8: 53:18
       }
   
       bb1: {
index b590be5370f1d41050f9fa2d0e0689832aaf094d..fd4dcb2265e61df2a0530bb17aca2151e9b61cf8 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:44:13: 44:14
 -         _2 = Eq(move _3, const 17_i8);   // scope 0 at $DIR/if-condition-int.rs:44:13: 44:20
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:44:19: 44:20
--         switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if-condition-int.rs:46:9: 46:14
+-         switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if-condition-int.rs:45:5: 45:12
 +         _2 = Eq(_3, const 17_i8);        // scope 0 at $DIR/if-condition-int.rs:44:13: 44:20
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:44:19: 44:20
-+         switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if-condition-int.rs:46:9: 46:14
++         switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if-condition-int.rs:45:5: 45:12
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 1 at $DIR/if-condition-int.rs:46:9: 46:14
++         StorageDead(_3);                 // scope 1 at $DIR/if-condition-int.rs:45:5: 45:12
           StorageLive(_6);                 // scope 1 at $DIR/if-condition-int.rs:47:23: 47:31
           StorageLive(_7);                 // scope 1 at $DIR/if-condition-int.rs:47:23: 47:24
           _7 = _2;                         // scope 1 at $DIR/if-condition-int.rs:47:23: 47:24
           StorageDead(_7);                 // scope 1 at $DIR/if-condition-int.rs:47:30: 47:31
           _0 = Add(const 100_i32, move _6); // scope 1 at $DIR/if-condition-int.rs:47:17: 47:31
           StorageDead(_6);                 // scope 1 at $DIR/if-condition-int.rs:47:30: 47:31
-          goto -> bb3;                     // scope 1 at $DIR/if-condition-int.rs:45:5: 48:6
+          goto -> bb3;                     // scope 1 at $DIR/if-condition-int.rs:47:30: 47:31
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 1 at $DIR/if-condition-int.rs:46:9: 46:14
++         StorageDead(_3);                 // scope 1 at $DIR/if-condition-int.rs:45:5: 45:12
           StorageLive(_4);                 // scope 1 at $DIR/if-condition-int.rs:46:23: 46:31
           StorageLive(_5);                 // scope 1 at $DIR/if-condition-int.rs:46:23: 46:24
           _5 = _2;                         // scope 1 at $DIR/if-condition-int.rs:46:23: 46:24
@@ -47,7 +47,7 @@
           StorageDead(_5);                 // scope 1 at $DIR/if-condition-int.rs:46:30: 46:31
           _0 = Add(const 10_i32, move _4); // scope 1 at $DIR/if-condition-int.rs:46:18: 46:31
           StorageDead(_4);                 // scope 1 at $DIR/if-condition-int.rs:46:30: 46:31
-          goto -> bb3;                     // scope 1 at $DIR/if-condition-int.rs:45:5: 48:6
+          goto -> bb3;                     // scope 1 at $DIR/if-condition-int.rs:46:30: 46:31
       }
   
       bb3: {
index 661591658df89c0c1ccc1d7fa5fbd1d3ba76c358..40de48385f02e3894129090d91eb2557ad08b780 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:21:8: 21:9
 -         _2 = Eq(move _3, const 'x');     // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:15: 21:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:21:15: 21:16
-+         switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
++         switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:21:19: 21:20
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:21:8: 21:16
           _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:21:30: 21:31
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:21:5: 21:33
       }
index 7d0ed7338d7d230651c980c4a14ad48f685dce61..28c36aed84c38270a3b9a705a4e2965416db6a21 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:25:8: 25:9
 -         _2 = Eq(move _3, const 42_i8);   // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:14: 25:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:25:14: 25:15
-+         switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
++         switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:25:18: 25:19
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:25:8: 25:15
           _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:25:29: 25:30
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:25:5: 25:32
       }
index bf388a141b617a198689e15a1f921fafd3e3fece..55932fee9600cb28a3644461026d20246356ee7e 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:33:8: 33:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:14: 33:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:33:14: 33:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:34:9: 34:10
           goto -> bb6;                     // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:5: 39:6
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:33:8: 33:15
           StorageLive(_4);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
           StorageLive(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:16
           _5 = _1;                         // scope 0 at $DIR/if-condition-int.rs:35:15: 35:16
 -         _4 = Ne(move _5, const 21_u32);  // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
 -         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:21: 35:22
--         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
+-         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:35:21: 35:22
-+         switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
++         switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
       }
   
       bb3: {
-+         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
++         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
           _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:36:9: 36:10
           goto -> bb5;                     // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
       }
   
       bb4: {
-+         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
++         StorageDead(_5);                 // scope 0 at $DIR/if-condition-int.rs:35:15: 35:22
           _0 = const 2_u32;                // scope 0 at $DIR/if-condition-int.rs:38:9: 38:10
           goto -> bb5;                     // scope 0 at $DIR/if-condition-int.rs:35:12: 39:6
       }
index bee2e030b7ed55126fb2b87e3e9655aee6c354ec..c4574b32a59991f086505352cc870fee9c1a7dac 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:29:8: 29:9
 -         _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:15: 29:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:29:15: 29:16
-+         switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
++         switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:29:19: 29:20
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:29:8: 29:16
           _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:29:30: 29:31
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:29:5: 29:33
       }
index 09a87591be10793a283ad2de3822e642b2db3b87..88d9d5622b8ec060a8d3ff45fcb66d7db8069218 100644 (file)
           _3 = _1;                         // scope 0 at $DIR/if-condition-int.rs:12:8: 12:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:14: 12:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
+-         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
 +         nop;                             // scope 0 at $DIR/if-condition-int.rs:12:14: 12:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
++         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
       }
   
       bb1: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
           _0 = const 0_u32;                // scope 0 at $DIR/if-condition-int.rs:12:18: 12:19
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
       }
   
       bb2: {
-+         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
++         StorageDead(_3);                 // scope 0 at $DIR/if-condition-int.rs:12:8: 12:15
           _0 = const 1_u32;                // scope 0 at $DIR/if-condition-int.rs:12:29: 12:30
           goto -> bb3;                     // scope 0 at $DIR/if-condition-int.rs:12:5: 12:32
       }
index 97ffd664463bb70f9ead3f2bcd0f102fa9450416..ce30b050d67d976c517c5c8b1afeab6d6fa8e1a7 100644 (file)
@@ -19,7 +19,7 @@
           _3 = _1;                         // scope 0 at $DIR/inline-diverging.rs:13:8: 13:9
           _2 = Gt(move _3, const 0_i32);   // scope 0 at $DIR/inline-diverging.rs:13:8: 13:13
           StorageDead(_3);                 // scope 0 at $DIR/inline-diverging.rs:13:12: 13:13
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline-diverging.rs:13:5: 17:6
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline-diverging.rs:13:8: 13:13
       }
   
       bb1: {
index 5ceefce6114f0410a39fb9e0b2bbb24b8421fcfe..0ff0e8ea7b1faea4f7b3d4791132e9287a35791a 100644 (file)
@@ -38,7 +38,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) }
         Retag(_10);                      // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         Retag(_4);                       // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
@@ -52,7 +52,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
         Retag(_9);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
index 226db9558ef46bce9622b8b751408caab69ecd18..3539fc8b4876c0a8e021c1080103b23c6435356c 100644 (file)
@@ -21,7 +21,7 @@
       }
   
       bb2: {
-          switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:9: 14:10
+          switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
       }
   
       bb3: {
index 8355b2d195e148d519123c0625eaddb82d405bbb..a2471e4308b0171169deb8cb78fc8ac833ea0cf7 100644 (file)
@@ -26,7 +26,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
         StorageLive(_4);                 // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
         _4 = _1;                         // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
-        switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-38669.rs:7:9: 9:10
+        switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue-38669.rs:7:12: 7:24
     }
 
     bb3: {
index 0417ed8c88b137a396a5aaef26d23426c77ab58f..54930937c9103f6f21a2c9f6f8b8ab25f8ba0b18 100644 (file)
@@ -26,14 +26,14 @@ fn main() -> () {
         _8 = const false;                // scope 0 at $DIR/issue-41888.rs:7:9: 7:10
         StorageLive(_1);                 // scope 0 at $DIR/issue-41888.rs:7:9: 7:10
         StorageLive(_2);                 // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
-        _2 = cond() -> [return: bb1, unwind: bb12]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
+        _2 = cond() -> [return: bb1, unwind: bb11]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
                                          // mir::Constant
                                          // + span: $DIR/issue-41888.rs:8:8: 8:12
                                          // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
+        switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue-41888.rs:8:8: 8:14
     }
 
     bb2: {
@@ -42,22 +42,26 @@ fn main() -> () {
         _4 = K;                          // scope 1 at $DIR/issue-41888.rs:9:18: 9:19
         _3 = E::F(move _4);              // scope 1 at $DIR/issue-41888.rs:9:13: 9:20
         StorageDead(_4);                 // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
-        goto -> bb15;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
+        goto -> bb14;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
     }
 
     bb3: {
-        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:14:6: 14:6
-        goto -> bb9;                     // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
+        goto -> bb4;                     // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
     }
 
     bb4: {
-        goto -> bb5;                     // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
+        StorageDead(_3);                 // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
+        _5 = discriminant(_1);           // scope 1 at $DIR/issue-41888.rs:10:16: 10:24
+        switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 1 at $DIR/issue-41888.rs:10:16: 10:24
     }
 
     bb5: {
-        StorageDead(_3);                 // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
-        _5 = discriminant(_1);           // scope 1 at $DIR/issue-41888.rs:10:16: 10:24
-        switchInt(move _5) -> [0_isize: bb7, otherwise: bb6]; // scope 1 at $DIR/issue-41888.rs:10:16: 10:24
+        StorageLive(_6);                 // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
+        _9 = const false;                // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
+        _6 = move ((_1 as F).0: K);      // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
+        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:10:29: 13:10
+        StorageDead(_6);                 // scope 1 at $DIR/issue-41888.rs:13:9: 13:10
+        goto -> bb8;                     // scope 1 at $DIR/issue-41888.rs:10:9: 13:10
     }
 
     bb6: {
@@ -66,24 +70,16 @@ fn main() -> () {
     }
 
     bb7: {
-        StorageLive(_6);                 // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
-        _9 = const false;                // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
-        _6 = move ((_1 as F).0: K);      // scope 1 at $DIR/issue-41888.rs:10:21: 10:23
-        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:10:29: 13:10
-        goto -> bb8;                     // scope 1 at $DIR/issue-41888.rs:10:9: 13:10
+        _0 = const ();                   // scope 1 at $DIR/issue-41888.rs:14:6: 14:6
+        goto -> bb8;                     // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
     }
 
     bb8: {
-        StorageDead(_6);                 // scope 1 at $DIR/issue-41888.rs:13:9: 13:10
-        goto -> bb9;                     // scope 1 at $DIR/issue-41888.rs:8:5: 14:6
-    }
-
-    bb9: {
         StorageDead(_2);                 // scope 1 at $DIR/issue-41888.rs:14:5: 14:6
-        goto -> bb21;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+        goto -> bb20;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb10: {
+    bb9: {
         _7 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
         _8 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
         _9 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
@@ -91,66 +87,66 @@ fn main() -> () {
         return;                          // scope 0 at $DIR/issue-41888.rs:15:2: 15:2
     }
 
-    bb11 (cleanup): {
-        goto -> bb12;                    // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
+    bb10 (cleanup): {
+        goto -> bb11;                    // scope 1 at $DIR/issue-41888.rs:9:19: 9:20
     }
 
-    bb12 (cleanup): {
-        goto -> bb13;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb11 (cleanup): {
+        goto -> bb12;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb13 (cleanup): {
+    bb12 (cleanup): {
         resume;                          // scope 0 at $DIR/issue-41888.rs:6:1: 15:2
     }
 
-    bb14 (cleanup): {
+    bb13 (cleanup): {
         _7 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _8 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _9 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _1 = move _3;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
-        goto -> bb11;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
+        goto -> bb10;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
     }
 
-    bb15: {
+    bb14: {
         _7 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _8 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _9 = const true;                 // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
         _1 = move _3;                    // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
-        goto -> bb4;                     // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
+        goto -> bb3;                     // scope 1 at $DIR/issue-41888.rs:9:9: 9:10
     }
 
-    bb16: {
+    bb15: {
         _7 = const false;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
-        goto -> bb10;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+        goto -> bb9;                     // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb17 (cleanup): {
-        goto -> bb13;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb16 (cleanup): {
+        goto -> bb12;                    // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb18: {
-        drop(_1) -> [return: bb16, unwind: bb13]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb17: {
+        drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb19 (cleanup): {
-        drop(_1) -> bb13;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb18 (cleanup): {
+        drop(_1) -> bb12;                // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb20: {
+    bb19: {
         _10 = discriminant(_1);          // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
-        switchInt(move _10) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+        switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb21: {
-        switchInt(_7) -> [false: bb16, otherwise: bb20]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb20: {
+        switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb22 (cleanup): {
+    bb21 (cleanup): {
         _11 = discriminant(_1);          // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
-        switchInt(move _11) -> [0_isize: bb17, otherwise: bb19]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+        switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 
-    bb23 (cleanup): {
-        switchInt(_7) -> [false: bb13, otherwise: bb22]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
+    bb22 (cleanup): {
+        switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue-41888.rs:15:1: 15:2
     }
 }
index 06fbbda3d9e2298b3c144ddcdd10eba2e6572416..2f8931382a69ee7d62fdae61b474eb2000b2df65 100644 (file)
@@ -25,7 +25,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
         _3 = const true;                 // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
         FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue-49232.rs:8:19: 8:23
-        switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue-49232.rs:9:17: 9:22
+        switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue-49232.rs:8:13: 8:23
     }
 
     bb3: {
@@ -39,7 +39,7 @@ fn main() -> () {
 
     bb5: {
         _2 = const 4_i32;                // scope 0 at $DIR/issue-49232.rs:9:26: 9:27
-        goto -> bb8;                     // scope 0 at $DIR/issue-49232.rs:8:13: 11:14
+        goto -> bb8;                     // scope 0 at $DIR/issue-49232.rs:9:26: 9:27
     }
 
     bb6: {
@@ -47,7 +47,7 @@ fn main() -> () {
     }
 
     bb7: {
-        goto -> bb8;                     // scope 0 at $DIR/issue-49232.rs:8:13: 11:14
+        goto -> bb8;                     // scope 0 at $DIR/issue-49232.rs:11:13: 11:14
     }
 
     bb8: {
index ba17a45f984ef403d6220c99866984ace687d64e..95efa74289d85b6509f813638dea5abf1ad5d257 100644 (file)
@@ -37,8 +37,8 @@ fn test() -> Option<Box<u32>> {
 
     bb1: {
         StorageDead(_4);                 // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-        _5 = discriminant(_3);           // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-        switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+        _5 = discriminant(_3);           // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+        switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
     }
 
     bb2: {
index e955feb7d1f41fcc9662be0f78863421ec2abe16..95632293d9991518f234eb31878b0ca98c49b66f 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index e955feb7d1f41fcc9662be0f78863421ec2abe16..95632293d9991518f234eb31878b0ca98c49b66f 100644 (file)
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index ff8c410a7268d4e1b289a6c96523d1c8aa5861cb..946aab9c6e898f270c31a248f6da6f0826d63559 100644 (file)
@@ -53,8 +53,8 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
           ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
           discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:3:9: 3:16
-          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:3:9: 3:16
+          _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:2:17: 2:30
       }
   
       bb1: {
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index ff8c410a7268d4e1b289a6c96523d1c8aa5861cb..946aab9c6e898f270c31a248f6da6f0826d63559 100644 (file)
@@ -53,8 +53,8 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
           ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
           discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:3:9: 3:16
-          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:3:9: 3:16
+          _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:2:17: 2:30
       }
   
       bb1: {
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 86ec31ce47edaa3edd82a0b79e83b3b0c140b33b..d028f0b989a68b7f1e81bd6521d1286562221cc1 100644 (file)
@@ -43,29 +43,29 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb1: {
-        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
         StorageLive(_3);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
         StorageLive(_4);                 // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
         _4 = _1;                         // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
-        _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
+        _3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb2; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
                                          // mir::Constant
                                          // + span: $DIR/issue-59352.rs:14:30: 14:38
                                          // + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
     }
 
     bb2: {
-        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
-        _0 = const 0_u32;                // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
-        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
-    }
-
-    bb3: {
         StorageDead(_4);                 // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
         StorageLive(_10);                // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
         _10 = discriminant(_3);          // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
     }
 
+    bb3: {
+        StorageDead(_11);                // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
+        _0 = const 0_u32;                // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
+        goto -> bb4;                     // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+    }
+
     bb4: {
         return;                          // scope 0 at $DIR/issue-59352.rs:15:2: 15:2
     }
@@ -82,7 +82,7 @@ fn num_to_digit(_1: char) -> u32 {
         StorageDead(_7);                 // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
         StorageDead(_5);                 // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
         StorageDead(_2);                 // scope 0 at $DIR/issue-59352.rs:14:22: 14:23
-        switchInt(move _11) -> [1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
+        switchInt(move _11) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
     }
 
     bb6: {
index 89ba5eeeef4e666557559f730388cd436a025200..4630c408750141cc7270e76e02f7e179013c6c75 100644 (file)
   
       bb1: {
           StorageDead(_3);                 // scope 2 at $DIR/issue-75439.rs:7:52: 7:53
-          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:9:13: 9:14
+          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
       }
   
       bb2: {
-          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:9:16: 9:17
+          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
       }
   
       bb3: {
-          switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:9:19: 9:20
+          switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
       }
   
       bb4: {
-          discriminant(_0) = 0;            // scope 1 at $DIR/issue-75439.rs:12:9: 12:13
-          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:9:5: 13:6
-      }
-  
-      bb5: {
           StorageLive(_5);                 // scope 1 at $DIR/issue-75439.rs:10:14: 10:38
           StorageLive(_6);                 // scope 4 at $DIR/issue-75439.rs:10:33: 10:35
           _6 = _4;                         // scope 4 at $DIR/issue-75439.rs:10:33: 10:35
-          _5 = transmute::<u32, [u8; 4]>(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:10:23: 10:36
+          _5 = transmute::<u32, [u8; 4]>(move _6) -> bb7; // scope 4 at $DIR/issue-75439.rs:10:23: 10:36
                                            // mir::Constant
                                            // + span: $DIR/issue-75439.rs:10:23: 10:32
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::<u32, [u8; 4]>}, val: Value(Scalar(<ZST>)) }
       }
   
-      bb6: {
+      bb5: {
           StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:9:27: 9:29
           _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:9:27: 9:29
-          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
+          goto -> bb4;                     // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
       }
   
-      bb7: {
+      bb6: {
           StorageLive(_4);                 // scope 1 at $DIR/issue-75439.rs:9:27: 9:29
           _4 = _2[3 of 4];                 // scope 1 at $DIR/issue-75439.rs:9:27: 9:29
-          goto -> bb5;                     // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
+          goto -> bb4;                     // scope 1 at $DIR/issue-75439.rs:9:12: 9:30
       }
   
-      bb8: {
+      bb7: {
           StorageDead(_6);                 // scope 4 at $DIR/issue-75439.rs:10:35: 10:36
           ((_0 as Some).0: [u8; 4]) = move _5; // scope 1 at $DIR/issue-75439.rs:10:9: 10:39
           discriminant(_0) = 1;            // scope 1 at $DIR/issue-75439.rs:10:9: 10:39
           StorageDead(_5);                 // scope 1 at $DIR/issue-75439.rs:10:38: 10:39
+          StorageDead(_4);                 // scope 1 at $DIR/issue-75439.rs:11:5: 11:6
+          goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:9:5: 13:6
+      }
+  
+      bb8: {
+          discriminant(_0) = 0;            // scope 1 at $DIR/issue-75439.rs:12:9: 12:13
           goto -> bb9;                     // scope 1 at $DIR/issue-75439.rs:9:5: 13:6
       }
   
       bb9: {
-          StorageDead(_4);                 // scope 1 at $DIR/issue-75439.rs:13:5: 13:6
           StorageDead(_2);                 // scope 0 at $DIR/issue-75439.rs:14:1: 14:2
           return;                          // scope 0 at $DIR/issue-75439.rs:14:2: 14:2
       }
index db88f77bb630e67d6b32c847ce6d724944e73e62..9e91603cee943292e50da84cc5b6f8071c58ebfc 100644 (file)
@@ -16,7 +16,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/loop_test.rs:10:5: 12:6
         StorageLive(_2);                 // scope 0 at $DIR/loop_test.rs:10:8: 10:12
         _2 = const true;                 // scope 0 at $DIR/loop_test.rs:10:8: 10:12
-        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:10:5: 12:6
+        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:10:8: 10:12
     }
 
     bb1: {
index acb8aca75904b1e9459531f0597c9832e03eb587..f427375e5a624ddbf9d5afd66e973362d980a02e 100644 (file)
@@ -50,7 +50,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[2]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
@@ -74,7 +74,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
-                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
@@ -98,7 +98,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
-                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
index d2056ac13a7ac79041d01b891de3ad0d50e77900..25db3b98c2562e1979071cbfed46e2e1a13d13b3 100644 (file)
@@ -33,7 +33,7 @@
           _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27
           StorageDead(_5);                 // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27
           StorageDead(_4);                 // scope 0 at $DIR/lower_slice_len.rs:5:26: 5:27
-          switchInt(move _3) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
+          switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:5:8: 5:27
       }
   
       bb2: {
           _7 = _1;                         // scope 0 at $DIR/lower_slice_len.rs:6:15: 6:20
           _8 = Len((*_2));                 // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
           _9 = Lt(_7, _8);                 // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
-          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb4; // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+          assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> bb3; // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
       }
   
       bb3: {
-          _0 = const 42_u8;                // scope 0 at $DIR/lower_slice_len.rs:8:9: 8:11
+          _0 = (*_2)[_7];                  // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
+          StorageDead(_7);                 // scope 0 at $DIR/lower_slice_len.rs:7:5: 7:6
           goto -> bb5;                     // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
       }
   
       bb4: {
-          _0 = (*_2)[_7];                  // scope 0 at $DIR/lower_slice_len.rs:6:9: 6:21
-          StorageDead(_7);                 // scope 0 at $DIR/lower_slice_len.rs:7:5: 7:6
+          _0 = const 42_u8;                // scope 0 at $DIR/lower_slice_len.rs:8:9: 8:11
           goto -> bb5;                     // scope 0 at $DIR/lower_slice_len.rs:5:5: 9:6
       }
   
index feb25035ee0ecef3d925ff777a19872b1e97191d..0917278875a57ba5c9aa09e6877c828576ee3840 100644 (file)
   
       bb0: {
 -         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match-arm-scopes.rs:14:11: 14:16
--         switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
-+         switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:15:10: 15:15
+-         switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
++         switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
       }
   
       bb1: {
 -         falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match-arm-scopes.rs:15:9: 15:22
-+         switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34
++         switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
       }
   
       bb2: {
--         switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:15:29: 15:34
-+         switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14
+-         switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
++         switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
       }
   
       bb3: {
@@ -51,7 +51,7 @@
 -     }
 - 
 -     bb4: {
--         switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:16:10: 16:14
+-         switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match-arm-scopes.rs:14:5: 14:16
 -     }
 - 
 -     bb5: {
@@ -85,8 +85,8 @@
           StorageLive(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
           StorageLive(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
           _10 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-+         switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-         switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
++         switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
       }
   
 -     bb9: {
 -     bb10: {
 +     bb7: {
           _9 = (*_6);                      // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
-          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
 +         switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
 -     bb11: {
 +     bb8: {
-          StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
   
 -     bb12: {
 +     bb9: {
+          StorageDead(_10);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
           StorageDead(_9);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageLive(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
           StorageLive(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
           _13 = _1;                        // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
--         switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
-+         switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
+-         switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
++         switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match-arm-scopes.rs:15:45: 15:49
       }
   
 -     bb14: {
 -     bb15: {
 +     bb12: {
           _12 = (*_6);                     // scope 0 at $DIR/match-arm-scopes.rs:15:70: 15:71
-          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
 +         switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match-arm-scopes.rs:15:42: 15:73
       }
   
 -     bb16: {
 +     bb13: {
-          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _3);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
 -         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
   
 -     bb17: {
 +     bb14: {
+          StorageDead(_13);                // scope 0 at $DIR/match-arm-scopes.rs:15:72: 15:73
           StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
 +     bb15: {
           StorageDead(_7);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_5);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
+          StorageDead(_12);                // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_8);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
           StorageDead(_6);                 // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
--         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
-+         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
++         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:15:77: 15:78
       }
   
 -     bb19: {
 +     bb18: {
           StorageDead(_16);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
           StorageDead(_15);                // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
--         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
-+         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:14:5: 17:6
+-         goto -> bb22;                    // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
++         goto -> bb19;                    // scope 0 at $DIR/match-arm-scopes.rs:16:41: 16:42
       }
   
 -     bb22: {
index c27ee528b80b7e457abd99aa28978ae2070cc49e..b2fbe225915b0f0aacbc7f20bc058205cfbfb89b 100644 (file)
@@ -28,13 +28,13 @@ fn full_tested_match() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
-        _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:16:9: 16:16
+        _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
+        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:15:13: 15:27
     }
 
     bb1: {
         _1 = (const 3_i32, const 3_i32); // scope 0 at $DIR/match_false_edges.rs:18:17: 18:23
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:15:13: 19:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:18:17: 18:23
     }
 
     bb2: {
@@ -57,7 +57,7 @@ fn full_tested_match() -> () {
                                          // + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
-                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
@@ -72,7 +72,6 @@ fn full_tested_match() -> () {
     }
 
     bb7: {
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match_false_edges.rs:16:26: 16:27
         StorageLive(_5);                 // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
@@ -82,8 +81,9 @@ fn full_tested_match() -> () {
         _1 = (const 1_i32, move _8);     // scope 2 at $DIR/match_false_edges.rs:16:31: 16:37
         StorageDead(_8);                 // scope 2 at $DIR/match_false_edges.rs:16:36: 16:37
         StorageDead(_5);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:15:13: 19:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:16:36: 16:37
     }
 
     bb8: {
@@ -100,7 +100,7 @@ fn full_tested_match() -> () {
         _1 = (const 2_i32, move _10);    // scope 3 at $DIR/match_false_edges.rs:17:20: 17:26
         StorageDead(_10);                // scope 3 at $DIR/match_false_edges.rs:17:25: 17:26
         StorageDead(_9);                 // scope 0 at $DIR/match_false_edges.rs:17:25: 17:26
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:15:13: 19:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:17:25: 17:26
     }
 
     bb10: {
index a4ebf8a02466a5160d5dd27806afba0f3bf4418b..8ff555dbb871e937055ba9c00c8dcda990585fe1 100644 (file)
@@ -27,8 +27,8 @@ fn full_tested_match2() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
-        _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:27:9: 27:16
+        _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:26:19: 26:27
+        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:26:13: 26:27
     }
 
     bb1: {
@@ -47,7 +47,7 @@ fn full_tested_match2() -> () {
         _1 = (const 2_i32, move _10);    // scope 3 at $DIR/match_false_edges.rs:29:20: 29:26
         StorageDead(_10);                // scope 3 at $DIR/match_false_edges.rs:29:25: 29:26
         StorageDead(_9);                 // scope 0 at $DIR/match_false_edges.rs:29:25: 29:26
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:26:13: 30:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:29:25: 29:26
     }
 
     bb4: {
@@ -70,7 +70,6 @@ fn full_tested_match2() -> () {
     }
 
     bb7: {
-        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         FakeRead(ForGuardBinding, _6);   // scope 0 at $DIR/match_false_edges.rs:27:26: 27:27
         StorageLive(_5);                 // scope 0 at $DIR/match_false_edges.rs:27:14: 27:15
@@ -80,8 +79,9 @@ fn full_tested_match2() -> () {
         _1 = (const 1_i32, move _8);     // scope 2 at $DIR/match_false_edges.rs:27:31: 27:37
         StorageDead(_8);                 // scope 2 at $DIR/match_false_edges.rs:27:36: 27:37
         StorageDead(_5);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
+        StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:26:13: 30:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:27:36: 27:37
     }
 
     bb8: {
@@ -92,7 +92,7 @@ fn full_tested_match2() -> () {
 
     bb9: {
         _1 = (const 3_i32, const 3_i32); // scope 0 at $DIR/match_false_edges.rs:28:17: 28:23
-        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:26:13: 30:6
+        goto -> bb10;                    // scope 0 at $DIR/match_false_edges.rs:28:17: 28:23
     }
 
     bb10: {
index 5de52b324f43ffd2813cca70ff7428ade62930af..3fb06cfe6385f429ef1c88dd7b28d7109b3b55fa 100644 (file)
@@ -38,8 +38,8 @@ fn main() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
         _2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
-        _4 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
-        switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:36:9: 36:17
+        _4 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:35:19: 35:26
+        switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:35:13: 35:26
     }
 
     bb1: {
@@ -55,7 +55,7 @@ fn main() -> () {
         _14 = _2;                        // scope 0 at $DIR/match_false_edges.rs:39:9: 39:11
         _1 = const 4_i32;                // scope 5 at $DIR/match_false_edges.rs:39:15: 39:16
         StorageDead(_14);                // scope 0 at $DIR/match_false_edges.rs:39:15: 39:16
-        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6
+        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:39:15: 39:16
     }
 
     bb4: {
@@ -78,15 +78,15 @@ fn main() -> () {
     }
 
     bb7: {
-        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         FakeRead(ForGuardBinding, _7);   // scope 0 at $DIR/match_false_edges.rs:36:27: 36:28
         StorageLive(_6);                 // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
         _6 = ((_2 as Some).0: i32);      // scope 0 at $DIR/match_false_edges.rs:36:14: 36:16
         _1 = const 1_i32;                // scope 2 at $DIR/match_false_edges.rs:36:32: 36:33
         StorageDead(_6);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
+        StorageDead(_8);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
         StorageDead(_7);                 // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
-        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6
+        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:36:32: 36:33
     }
 
     bb8: {
@@ -100,7 +100,7 @@ fn main() -> () {
         _9 = _2;                         // scope 0 at $DIR/match_false_edges.rs:37:9: 37:11
         _1 = const 2_i32;                // scope 3 at $DIR/match_false_edges.rs:37:15: 37:16
         StorageDead(_9);                 // scope 0 at $DIR/match_false_edges.rs:37:15: 37:16
-        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6
+        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:37:15: 37:16
     }
 
     bb10: {
@@ -117,23 +117,24 @@ fn main() -> () {
     }
 
     bb11: {
-        StorageDead(_13);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         switchInt(move _12) -> [false: bb13, otherwise: bb12]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
     }
 
     bb12: {
-        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
+        StorageDead(_13);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         FakeRead(ForGuardBinding, _11);  // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         StorageLive(_10);                // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
         _10 = ((_2 as Some).0: i32);     // scope 0 at $DIR/match_false_edges.rs:38:14: 38:15
         _1 = const 3_i32;                // scope 4 at $DIR/match_false_edges.rs:38:33: 38:34
         StorageDead(_10);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
+        StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         StorageDead(_11);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
-        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:35:13: 40:6
+        goto -> bb14;                    // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
     }
 
     bb13: {
+        StorageDead(_13);                // scope 0 at $DIR/match_false_edges.rs:38:28: 38:29
         StorageDead(_12);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         StorageDead(_11);                // scope 0 at $DIR/match_false_edges.rs:38:33: 38:34
         falseEdge -> [real: bb3, imaginary: bb3]; // scope 0 at $DIR/match_false_edges.rs:38:20: 38:29
index 5bb910947ca2523556cea829e733822e11189d7f..6cb27d244440dda62d02c17fabc8f9a6b59477c8 100644 (file)
@@ -42,7 +42,7 @@ fn main() -> () {
 
     bb3: {
         _3 = const 3_i32;                // scope 2 at $DIR/match_test.rs:16:14: 16:15
-        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:12:5: 17:6
+        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:16:14: 16:15
     }
 
     bb4: {
@@ -60,7 +60,7 @@ fn main() -> () {
     }
 
     bb7: {
-        switchInt(_1) -> [-1_i32: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:15:9: 15:11
+        switchInt(_1) -> [-1_i32: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:12:5: 12:12
     }
 
     bb8: {
@@ -75,10 +75,10 @@ fn main() -> () {
     }
 
     bb10: {
-        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:23: 13:24
         FakeRead(ForMatchGuard, _8);     // scope 2 at $DIR/match_test.rs:13:18: 13:19
         _3 = const 0_i32;                // scope 2 at $DIR/match_test.rs:13:23: 13:24
-        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:12:5: 17:6
+        StorageDead(_9);                 // scope 2 at $DIR/match_test.rs:13:23: 13:24
+        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:13:23: 13:24
     }
 
     bb11: {
@@ -88,12 +88,12 @@ fn main() -> () {
 
     bb12: {
         _3 = const 1_i32;                // scope 2 at $DIR/match_test.rs:14:20: 14:21
-        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:12:5: 17:6
+        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:14:20: 14:21
     }
 
     bb13: {
         _3 = const 2_i32;                // scope 2 at $DIR/match_test.rs:15:15: 15:16
-        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:12:5: 17:6
+        goto -> bb14;                    // scope 2 at $DIR/match_test.rs:15:15: 15:16
     }
 
     bb14: {
index a52c6ae351b2c1be84c072ff71c57a13ce5ae52e..d164f62c580f72206b8cbfdd36cae25a26bb877e 100644 (file)
@@ -10,7 +10,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:36:9: 36:10
       let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:36:12: 36:13
       let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:36:15: 36:16
-+     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:19:5: 19:12
       scope 1 {
           debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:14:9: 14:10
           let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:15:9: 15:10
@@ -33,7 +33,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:16:9: 16:10
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:17:9: 17:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
--         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
 -     }
 - 
 -     bb1: {
 -         _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:22
 -         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:30:13: 30:22
 -         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:31:13: 31:21
--         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
+-         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:32:13: 32:15
 -     }
 - 
 -     bb2: {
 -         _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
 -         _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
-+         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
-+         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
++         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
 +         _2 = Ne(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
 +         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
           _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:23:13: 23:22
           _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:24:13: 24:21
--         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
+-         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:25:13: 25:15
 -     }
 - 
 -     bb3: {
-+         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
           StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
           StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:36:6: 36:7
           _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:36:6: 36:7
index a52c6ae351b2c1be84c072ff71c57a13ce5ae52e..d164f62c580f72206b8cbfdd36cae25a26bb877e 100644 (file)
@@ -10,7 +10,7 @@
       let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:36:9: 36:10
       let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:36:12: 36:13
       let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:36:15: 36:16
-+     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++     let mut _11: i32;                    // in scope 0 at $DIR/matches_reduce_branches.rs:19:5: 19:12
       scope 1 {
           debug a => _2;                   // in scope 1 at $DIR/matches_reduce_branches.rs:14:9: 14:10
           let _3: bool;                    // in scope 1 at $DIR/matches_reduce_branches.rs:15:9: 15:10
@@ -33,7 +33,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:16:9: 16:10
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:17:9: 17:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
--         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
+-         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
 -     }
 - 
 -     bb1: {
 -         _3 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:22
 -         _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:30:13: 30:22
 -         _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:31:13: 31:21
--         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
+-         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:32:13: 32:15
 -     }
 - 
 -     bb2: {
 -         _2 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
 -         _3 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
-+         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
-+         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++         StorageLive(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
++         _11 = _1;                        // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
 +         _2 = Ne(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
 +         _3 = Eq(_11, const 7_i32);       // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
           _4 = const false;                // scope 4 at $DIR/matches_reduce_branches.rs:23:13: 23:22
           _5 = const true;                 // scope 4 at $DIR/matches_reduce_branches.rs:24:13: 24:21
--         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 34:6
+-         goto -> bb3;                     // scope 4 at $DIR/matches_reduce_branches.rs:25:13: 25:15
 -     }
 - 
 -     bb3: {
-+         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:20:9: 20:10
++         StorageDead(_11);                // scope 4 at $DIR/matches_reduce_branches.rs:19:5: 19:12
           StorageDead(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
           StorageLive(_7);                 // scope 4 at $DIR/matches_reduce_branches.rs:36:6: 36:7
           _7 = _2;                         // scope 4 at $DIR/matches_reduce_branches.rs:36:6: 36:7
index 96b03477d01085fba9ef24cb8cb0be116daf6d7e..29f66ceac981e75c6372b06688d9006954dbdc5f 100644 (file)
@@ -5,11 +5,11 @@
       debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:7:8: 7:11
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:7:25: 7:25
       let mut _2: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+     let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
++     let mut _3: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
--         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:8:17: 8:20
+-         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb1: {
@@ -21,9 +21,9 @@
 -     }
 - 
 -     bb3: {
-+         StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+         _3 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
++         StorageLive(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _3 = move _2;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:11:2: 11:2
       }
   }
index 96b03477d01085fba9ef24cb8cb0be116daf6d7e..29f66ceac981e75c6372b06688d9006954dbdc5f 100644 (file)
@@ -5,11 +5,11 @@
       debug bar => _1;                     // in scope 0 at $DIR/matches_reduce_branches.rs:7:8: 7:11
       let mut _0: ();                      // return place in scope 0 at $DIR/matches_reduce_branches.rs:7:25: 7:25
       let mut _2: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+     let mut _3: isize;                   // in scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
++     let mut _3: isize;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
--         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:8:17: 8:20
+-         switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb1: {
@@ -21,9 +21,9 @@
 -     }
 - 
 -     bb3: {
-+         StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+         _3 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
-+         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:8:22: 8:26
++         StorageLive(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         _3 = move _2;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         StorageDead(_3);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:11:2: 11:2
       }
   }
index 410320e643cad2cf98f44cef36aa1fde0da9e820..4a9982d7699a8fb42f897bbc9c11cf7e2f43507a 100644 (file)
   fn match_nested_if() -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29
       let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12
-      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:23
-      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
-+     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
+      let mut _2: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++     let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++     let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
       scope 1 {
           debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12
-          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:23
-          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
-          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
--         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+-         switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
 -     }
 - 
 -     bb1: {
--         _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35
+-         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35
 -         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb2: {
--         _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
+-         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
 -         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb3: {
-+         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
-+         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52
--         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
++         StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++         _5 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++         _3 = Ne(_5, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
++         StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52
+-         switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb4: {
--         _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59
+-         _2 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59
 -         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb5: {
--         _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
+-         _2 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
 -         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb6: {
-+         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
-+         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76
--         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
++         StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++         _6 = move _3;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++         _2 = Ne(_6, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
++         StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76
+-         switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb7: {
--         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:42:13: 42:17
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb8: {
--         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:44:13: 44:18
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb9: {
-+         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:44:13: 44:18
-+         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb10: {
-+         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
++         _7 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
--         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 50:6
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
 -     }
 - 
--     bb11: {
--         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+-     bb8: {
+-         StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
--         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 50:6
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
 -     }
 - 
--     bb12: {
-+         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
-+         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:50:6: 50:7
+-     bb9: {
++         _1 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
           _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8
           StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2
index 410320e643cad2cf98f44cef36aa1fde0da9e820..4a9982d7699a8fb42f897bbc9c11cf7e2f43507a 100644 (file)
   fn match_nested_if() -> bool {
       let mut _0: bool;                    // return place in scope 0 at $DIR/matches_reduce_branches.rs:39:25: 39:29
       let _1: bool;                        // in scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12
-      let mut _2: ();                      // in scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:23
-      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-      let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-      let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
-+     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+     let mut _8: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+     let mut _9: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+     let mut _10: bool;                   // in scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
+      let mut _2: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+      let mut _3: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+      let mut _4: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++     let mut _5: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++     let mut _6: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++     let mut _7: bool;                    // in scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
       scope 1 {
           debug val => _1;                 // in scope 1 at $DIR/matches_reduce_branches.rs:40:9: 40:12
       }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:9: 40:12
-          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:40:21: 40:23
-          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-          StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-          StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
-          _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
--         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageLive(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+          StorageLive(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageLive(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+          _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+-         switchInt(move _4) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
 -     }
 - 
 -     bb1: {
--         _5 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35
+-         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:31: 41:35
 -         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb2: {
--         _5 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
+-         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
 -         goto -> bb3;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb3: {
-+         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+         _7 = move _6;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-+         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
-+         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
-          StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52
--         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
++         StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++         _5 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
++         _3 = Ne(_5, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:45: 41:50
++         StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:24: 41:28
+          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:51: 41:52
+-         switchInt(move _3) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
 -     }
 - 
 -     bb4: {
--         _4 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59
+-         _2 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:41:55: 41:59
 -         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb5: {
--         _4 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
+-         _2 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
 -         goto -> bb6;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb6: {
-+         StorageLive(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+         _8 = move _5;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-+         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
-+         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
-          StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76
--         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
++         StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++         _6 = move _3;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
++         _2 = Ne(_6, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:41:69: 41:74
++         StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:21: 41:52
+          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:75: 41:76
+-         switchInt(move _2) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
 -     }
 - 
 -     bb7: {
--         _3 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:42:13: 42:17
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb8: {
--         _3 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:44:13: 44:18
--         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb9: {
-+         StorageLive(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _9 = move _4;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _3 = Ne(_9, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:44:13: 44:18
-+         StorageDead(_9);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_4);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
--     }
-- 
--     bb10: {
-+         StorageLive(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-+         _10 = move _3;                   // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
++         StorageLive(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
++         _7 = move _2;                    // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
+          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:47:13: 47:17
--         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 50:6
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
 -     }
 - 
--     bb11: {
--         StorageDead(_3);                 // scope 0 at $DIR/matches_reduce_branches.rs:48:9: 48:10
+-     bb8: {
+-         StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:45:9: 45:10
 -         _1 = const false;                // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
--         goto -> bb12;                    // scope 0 at $DIR/matches_reduce_branches.rs:40:15: 50:6
+-         goto -> bb9;                     // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
 -     }
 - 
--     bb12: {
-+         _1 = Ne(_10, const false);       // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
-+         StorageDead(_10);                // scope 0 at $DIR/matches_reduce_branches.rs:41:15: 45:10
-          StorageDead(_2);                 // scope 0 at $DIR/matches_reduce_branches.rs:50:6: 50:7
+-     bb9: {
++         _1 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:49:14: 49:19
++         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:41:18: 41:76
           _0 = _1;                         // scope 1 at $DIR/matches_reduce_branches.rs:51:5: 51:8
           StorageDead(_1);                 // scope 0 at $DIR/matches_reduce_branches.rs:52:1: 52:2
           return;                          // scope 0 at $DIR/matches_reduce_branches.rs:52:2: 52:2
index 9fde4888809d165972579a47539fb615341c9a95..711cc31f49f98cc7eea0e5e900e37abcb832e44d 100644 (file)
@@ -7,18 +7,18 @@
       let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:12:11: 12:12
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:12:5: 12:12
       }
   
       bb1: {
           _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
       }
   
       bb2: {
           _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
       }
   
       bb3: {
index 9fde4888809d165972579a47539fb615341c9a95..711cc31f49f98cc7eea0e5e900e37abcb832e44d 100644 (file)
@@ -7,18 +7,18 @@
       let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:12:11: 12:12
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:12:5: 12:12
       }
   
       bb1: {
           _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
       }
   
       bb2: {
           _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
       }
   
       bb3: {
index 2dd0a3edb479a9c9db3c774a25391cdbb73e72c3..6bdeccbf913e65ce593cc233ed47feda300be2fe 100644 (file)
@@ -7,18 +7,18 @@
       let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:20:11: 20:12
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:20:5: 20:12
       }
   
       bb1: {
           _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
       }
   
       bb2: {
           _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
       }
   
       bb3: {
index 2dd0a3edb479a9c9db3c774a25391cdbb73e72c3..6bdeccbf913e65ce593cc233ed47feda300be2fe 100644 (file)
@@ -7,18 +7,18 @@
       let mut _2: isize;                   // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+          _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:20:11: 20:12
+          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:20:5: 20:12
       }
   
       bb1: {
           _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
       }
   
       bb2: {
           _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
       }
   
       bb3: {
index 39e6cee11b4c9c8a6e9fca6a08e2316f1f2a58d0..3ef7844ce434ffe161ca05f57d617bd2a8bd4f3a 100644 (file)
@@ -5,16 +5,16 @@
 | '_#1r | Local | ['_#1r]
 |
 | Inferred Region Values
-| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
-| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
+| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
+| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
 | '_#2r | U0 | {}
 | '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
 | '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
 | '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
-| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
-| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
 | '_#5r live at {bb1[4..=7], bb2[0..=2]}
@@ -63,32 +63,32 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
     }
 
     bb2: {
         StorageLive(_8);                 // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
         StorageLive(_9);                 // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
         _9 = (*_6);                      // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb4, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb3: {
-        StorageLive(_10);                // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb5, unwind: bb7]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-                                         // mir::Constant
-                                         // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
-                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
+        StorageDead(_9);                 // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
+        StorageDead(_8);                 // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
+        goto -> bb6;                     // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb4: {
-        StorageDead(_9);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
-        StorageDead(_8);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
-        goto -> bb6;                     // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageLive(_10);                // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x00000016)): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+                                         // mir::Constant
+                                         // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
+                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb5: {
index 6021b6529f911f81110faf21750685aad4452d35..d6b4a0beebd657a6751de68d0dfde771bd9d252d 100644 (file)
@@ -5,16 +5,16 @@
 | '_#1r | Local | ['_#1r]
 |
 | Inferred Region Values
-| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
-| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
+| '_#0r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#0r, '_#1r}
+| '_#1r | U0 | {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0], '_#1r}
 | '_#2r | U0 | {}
 | '_#3r | U0 | {bb1[0..=7], bb2[0..=2]}
 | '_#4r | U0 | {bb1[1..=7], bb2[0..=2]}
 | '_#5r | U0 | {bb1[4..=7], bb2[0..=2]}
 |
 | Inference Constraints
-| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
-| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=1], bb4[0..=3], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#0r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
+| '_#1r live at {bb0[0..=8], bb1[0..=7], bb2[0..=3], bb3[0..=3], bb4[0..=1], bb5[0..=2], bb6[0..=5], bb7[0]}
 | '_#3r live at {bb1[0]}
 | '_#4r live at {bb1[1..=3]}
 | '_#5r live at {bb1[4..=7], bb2[0..=2]}
@@ -63,32 +63,32 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const Const(Value(Scalar(0x01)): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb3, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
     }
 
     bb2: {
         StorageLive(_8);                 // bb2[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
         StorageLive(_9);                 // bb2[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
         _9 = (*_6);                      // bb2[2]: scope 3 at $DIR/region-subtyping-basic.rs:21:15: 21:17
-        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb4, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
+        _8 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(move _9) -> [return: bb3, unwind: bb7]; // bb2[3]: scope 3 at $DIR/region-subtyping-basic.rs:21:9: 21:18
                                          // mir::Constant
                                          // + span: $DIR/region-subtyping-basic.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb3: {
-        StorageLive(_10);                // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb5, unwind: bb7]; // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
-                                         // mir::Constant
-                                         // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
-                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
+        StorageDead(_9);                 // bb3[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
+        StorageDead(_8);                 // bb3[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
+        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb3[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
+        goto -> bb6;                     // bb3[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
     }
 
     bb4: {
-        StorageDead(_9);                 // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:21:17: 21:18
-        StorageDead(_8);                 // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:21:18: 21:19
-        _0 = const Const(Value(Scalar(<ZST>)): ()); // bb4[2]: scope 3 at $DIR/region-subtyping-basic.rs:20:13: 22:6
-        goto -> bb6;                     // bb4[3]: scope 3 at $DIR/region-subtyping-basic.rs:20:5: 24:6
+        StorageLive(_10);                // bb4[0]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+        _10 = Const(Value(Scalar(<ZST>)): fn(usize) -> bool {use_x})(const Const(Value(Scalar(0x0000000000000016)): usize)) -> [return: bb5, unwind: bb7]; // bb4[1]: scope 3 at $DIR/region-subtyping-basic.rs:23:9: 23:18
+                                         // mir::Constant
+                                         // + span: $DIR/region-subtyping-basic.rs:23:9: 23:14
+                                         // + literal: Const { ty: fn(usize) -> bool {use_x}, val: Value(Scalar(<ZST>)) }
     }
 
     bb5: {
index 8a1134478d6b597eb402a46f5d72b31be50e745e..cc4457cc5f3ff77f09a63da8662b46c568b323aa 100644 (file)
@@ -14,8 +14,8 @@ fn unwrap(_1: Option<T>) -> T {
     }
 
     bb0: {
-        _2 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:9: 9:16
-        switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:9:9: 9:16
+        _2 = discriminant(_1);           // scope 0 at $DIR/no-drop-for-inactive-variant.rs:8:11: 8:14
+        switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no-drop-for-inactive-variant.rs:8:5: 8:14
     }
 
     bb1: {
index 6fe28c0149e3070de989a3c828fdd76ccc6916b3..249db1c8a5ab29c7dc8c00aad368d0825785823e 100644 (file)
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const false);   // scope 0 at $DIR/not_equal_false.rs:4:8: 4:18
 +         _2 = move _3;                    // scope 0 at $DIR/not_equal_false.rs:4:8: 4:18
           StorageDead(_3);                 // scope 0 at $DIR/not_equal_false.rs:4:17: 4:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:4:5: 4:35
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:4:8: 4:18
       }
   
       bb1: {
index 4aa388fc67bd0204208e5795f831e03a17d663e8..eacc99dcf496632f46482177f0e79718f8fc5709 100644 (file)
       bb0: {
 -         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
-          _3 = discriminant(_1);           // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16
+          _3 = discriminant(_1);           // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
+          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:7:5: 7:12
       }
   
       bb1: {
           _0 = const 1_i32;                // scope 0 at $DIR/remove_fake_borrows.rs:9:14: 9:15
-          goto -> bb7;                     // scope 0 at $DIR/remove_fake_borrows.rs:7:5: 10:6
+          goto -> bb7;                     // scope 0 at $DIR/remove_fake_borrows.rs:9:14: 9:15
       }
   
       bb2: {
-          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0_i32: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:8:14: 8:15
+          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0_i32: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:7:5: 7:12
       }
   
       bb3: {
@@ -47,7 +47,6 @@
       }
   
       bb5: {
-          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
 -         FakeRead(ForMatchGuard, _4);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 -         FakeRead(ForMatchGuard, _5);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 -         FakeRead(ForMatchGuard, _6);     // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
@@ -57,7 +56,8 @@
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
           _0 = const 0_i32;                // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
-          goto -> bb7;                     // scope 0 at $DIR/remove_fake_borrows.rs:7:5: 10:6
+          StorageDead(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
+          goto -> bb7;                     // scope 0 at $DIR/remove_fake_borrows.rs:8:25: 8:26
       }
   
       bb6: {
index 80024124dc523d4c535fff3e14945b4b62af2067..6d6c2721973f80374c489324889c8d7f2f9fb097 100644 (file)
       bb4: {
 -         StorageDead(_18);                // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
 -         StorageDead(_9);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
-          _11 = discriminant(_8);          // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
-          switchInt(move _11) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
+          _11 = discriminant(_8);          // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
+          switchInt(move _11) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
       }
   }
   
index 787310d072a9b72c2439d14ebca60eea750f4d03..ee99d033af320bca56f544145470c42330804b3c 100644 (file)
@@ -127,7 +127,7 @@ fn array_casts() -> () {
                                          // + val: Unevaluated(array_casts, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
index 8abc6a3e4b515d7127e0f9306f180f893aff0b52..cdf7282c8c3c465ce43fd8c10c2dab0742cbbb63 100644 (file)
@@ -153,7 +153,7 @@ fn main() -> () {
                                          // + val: Unevaluated(main, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
index 57299cee7b726782b78088124bfff9ee901cd54f..d5190cdb0c7def75efcfd47b5e4aef4e0baa81c2 100644 (file)
           StorageDead(_13);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
           StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         _5 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         _5 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
       }
   
       bb4: {
           StorageDead(_11);                // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
           StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         _5 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         _5 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
       }
   }
   
index 4bfd0842db08407280e5065aeab7475e5386d8bf..69f3bec6fea25b4de91b4d303692d7221a2b71de 100644 (file)
@@ -64,8 +64,8 @@
       bb1: {
 -         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
 -         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
--         switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
+-         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
+-         switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
 -     }
 - 
 -     bb2: {
 -         goto -> bb1;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
 +         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
       }
   
 -     bb5: {
 -         goto -> bb1;                     // scope 5 at $DIR/separate_const_switch.rs:29:8: 29:10
 +         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
-+         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:9: 29:10
++         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
++         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:29:8: 29:10
       }
   }
   
index 973b7838eca35808a222861da4736ce815043136..5316c34fb37d1151377d85bc93c9d1f3dad0225d 100644 (file)
@@ -29,8 +29,8 @@
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
-          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
-          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:15:15: 15:16
+          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:15:9: 15:16
       }
   
       bb1: {
           discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
           StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
--         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
--         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         _8 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+-         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
++         _8 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
++         switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
       }
   
       bb2: {
           discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
           StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
--         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
--         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         _8 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+-         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
++         _8 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
++         switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
       }
   
       bb3: {
@@ -68,7 +68,7 @@
           _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
           discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
           StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
-          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
       }
   
       bb4: {
@@ -80,7 +80,7 @@
           discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
           StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
           StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
-          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
       }
   
       bb5: {
index cc941f251cea5fadf07a36229ea5ccae2312cf52..38ad12157e279cf1f1ca128c4cf3e632a37672d1 100644 (file)
@@ -27,8 +27,8 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
-        _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
-        switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+        _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:15:15: 15:16
+        switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:15:9: 15:16
     }
 
     bb1: {
@@ -44,7 +44,7 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
         _10 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
         discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
-        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
     }
 
     bb2: {
@@ -64,7 +64,7 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
         discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
         StorageDead(_9);                 // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
         StorageDead(_8);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
-        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
     }
 
     bb3: {
index ce32227ed653b87e82d3fd592b79cd009cd85510..0b5b9a490c62b07e7d8597633563e0aa9f36e1a9 100644 (file)
@@ -29,8 +29,8 @@
   
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
-          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
-          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:16:13: 16:18
+          _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:15:15: 15:16
+          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:15:9: 15:16
       }
   
       bb1: {
@@ -42,9 +42,9 @@
           discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:17:23: 17:44
           StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:17:43: 17:44
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
--         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
-+         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+-         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:17:43: 17:44
++         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
++         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
       }
   
       bb2: {
           discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:16:22: 16:46
           StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:16:45: 16:46
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
--         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:15:9: 18:10
+-         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:16:45: 16:46
 -     }
 - 
 -     bb3: {
-          _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
--         switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
-+         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:20:9: 20:33
+          _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:14:11: 19:6
+-         switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
++         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:14:5: 19:6
       }
   
 -     bb4: {
@@ -71,8 +71,8 @@
           _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:21:28: 21:29
           discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:21:34: 21:38
           StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
--         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
-+         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+-         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
++         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:21:37: 21:38
       }
   
 -     bb5: {
@@ -85,8 +85,8 @@
           discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:20:37: 20:44
           StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:20:43: 20:44
           StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
--         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
-+         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:14:5: 22:6
+-         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
++         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:20:43: 20:44
       }
   
 -     bb6: {
index 841cca7c381f78670161de9738aff47375aaed64..c189c18d2d0e741414580ee9ecb92907a77f27c3 100644 (file)
@@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12
-        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
+        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:6:5: 6:12
     }
 
     bb1: {
@@ -15,12 +15,12 @@ fn match_bool(_1: bool) -> usize {
 
     bb2: {
         _0 = const 20_usize;             // scope 0 at $DIR/simple-match.rs:8:14: 8:16
-        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:6:5: 9:6
+        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:8:14: 8:16
     }
 
     bb3: {
         _0 = const 10_usize;             // scope 0 at $DIR/simple-match.rs:7:17: 7:19
-        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:6:5: 9:6
+        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:7:17: 7:19
     }
 
     bb4: {
index 841cca7c381f78670161de9738aff47375aaed64..c189c18d2d0e741414580ee9ecb92907a77f27c3 100644 (file)
@@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple-match.rs:6:11: 6:12
-        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:7:9: 7:13
+        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple-match.rs:6:5: 6:12
     }
 
     bb1: {
@@ -15,12 +15,12 @@ fn match_bool(_1: bool) -> usize {
 
     bb2: {
         _0 = const 20_usize;             // scope 0 at $DIR/simple-match.rs:8:14: 8:16
-        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:6:5: 9:6
+        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:8:14: 8:16
     }
 
     bb3: {
         _0 = const 10_usize;             // scope 0 at $DIR/simple-match.rs:7:17: 7:19
-        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:6:5: 9:6
+        goto -> bb4;                     // scope 0 at $DIR/simple-match.rs:7:17: 7:19
     }
 
     bb4: {
index e390662307e04824f79809b9088b499765465f41..ad47891294a08af16169a922fe78420aade20935 100644 (file)
       }
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
-          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
+          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
+          switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:10:5: 10:12
       }
   
       bb1: {
           discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
       }
   
       bb2: {
@@ -36,7 +36,7 @@
 -         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
 -         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
 +         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
       }
   
       bb4: {
index 81a0e6ba0b4eeb91e6eaad55080564845e5a1979..52c036a77007c31d3f458f6b4e1c6acce76890ee 100644 (file)
       }
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
--         switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16
+          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12
+-         switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:10:5: 10:12
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 10:12
       }
   
       bb1: {
 -         discriminant(_0) = 0;            // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21
 -     }
 - 
 -     bb2: {
@@ -28,8 +28,8 @@
 - 
 -     bb3: {
           _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
-+         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:11:26: 11:27
       }
   
 -     bb4: {
index 40c18fb7282ecda2cffebe159df1b6d9d663a736..b24bdea9b715d9f308ee6f07933085eda44cdf48 100644 (file)
@@ -19,8 +19,8 @@
       }
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
+          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:17:5: 17:12
       }
   
       bb1: {
@@ -33,7 +33,7 @@
 -         StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
 -         StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
 +         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
       }
   
       bb2: {
@@ -50,7 +50,7 @@
 -         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
 -         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
 +         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
       }
   
       bb4: {
index 596dbabead0bf62b0e78a4e9751f1f65175b7d42..4d6a4edb08ae5f9070e905df0431e83933e1d29c 100644 (file)
       }
   
       bb0: {
-          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
--         switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
+          _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
+-         switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:17:5: 17:12
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 17:12
       }
   
       bb1: {
 -         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:19:24: 19:25
 -     }
 - 
 -     bb2: {
@@ -33,8 +33,8 @@
 - 
 -     bb3: {
           _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
-+         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:18:22: 18:23
       }
   
 -     bb4: {
index a3bad4f0c623deec6f12bee391a01d1a0cdfc94d..272a6756f39f2e5852bfaf432ce5a2c07463faf8 100644 (file)
@@ -45,8 +45,8 @@
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
           _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
-          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:36:13: 36:33
       }
   
       bb1: {
index b6b7511b3f597aaf947ef78c8b876babaa1b40d4..651a37f5a97223e4523618d8b8283037efff639c 100644 (file)
@@ -40,9 +40,9 @@
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
           _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
--         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+-         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:36:13: 36:33
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:36:13: 36:33
       }
   
       bb1: {
index 7495b0d407d2ca9d0ef27fc4583b0e80d10e98fb..512d9fe172b9fde0d1556aa0907ac270625b58a8 100644 (file)
           ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
           discriminant(_1) = 0;            // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
           StorageLive(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
-          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
-          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
+          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:19:24: 19:25
+          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:25
       }
   
       bb1: {
           ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
           discriminant(_2) = 0;            // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
       }
   
       bb2: {
@@ -45,7 +45,7 @@
           discriminant(_2) = 0;            // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
           StorageDead(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:20:34: 20:35
           StorageDead(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:20:34: 20:35
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:20:34: 20:35
       }
   
       bb4: {
index 7495b0d407d2ca9d0ef27fc4583b0e80d10e98fb..512d9fe172b9fde0d1556aa0907ac270625b58a8 100644 (file)
           ((_1 as Foo).0: u8) = const 0_u8; // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
           discriminant(_1) = 0;            // scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29
           StorageLive(_2);                 // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
-          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
-          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20
+          _3 = const 0_isize;              // scope 1 at $DIR/simplify-arm-identity.rs:19:24: 19:25
+          goto -> bb3;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:25
       }
   
       bb1: {
           ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
           discriminant(_2) = 0;            // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32
       }
   
       bb2: {
@@ -45,7 +45,7 @@
           discriminant(_2) = 0;            // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35
           StorageDead(_5);                 // scope 3 at $DIR/simplify-arm-identity.rs:20:34: 20:35
           StorageDead(_4);                 // scope 1 at $DIR/simplify-arm-identity.rs:20:34: 20:35
-          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6
+          goto -> bb4;                     // scope 1 at $DIR/simplify-arm-identity.rs:20:34: 20:35
       }
   
       bb4: {
index f72a12a5be0bca7852fa387310b4356a8253ea3b..eac9328500d29eb82525575bfd037f87a10a2fb9 100644 (file)
@@ -21,9 +21,9 @@
       }
   
 -     bb2: {
--         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
+-         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
 +     bb1: {
-+         switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
++         switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
       }
   
 -     bb3: {
index 9857322053ff93572ad0d7bb1ecee4e4021cfd6e..f5ac2a41f5f5bf5d98be781f4c634aba5ae7f3a2 100644 (file)
       }
   
       bb1: {
--         falseUnwind -> [real: bb2, cleanup: bb10]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+-         falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
 -     }
 - 
 -     bb2: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
--         _2 = bar() -> [return: bb3, unwind: bb10]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+-         _2 = bar() -> [return: bb3, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
 +         _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
                                            // mir::Constant
                                            // + span: $DIR/simplify_cfg.rs:9:12: 9:15
       }
   
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
+-         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
 +     bb2: {
-+         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
++         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
       }
   
 -     bb4: {
 +     bb3: {
           _0 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
--         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
+-         goto -> bb10;                    // scope 0 at $DIR/simplify_cfg.rs:10:13: 10:18
 +         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
 +         return;                          // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
       }
   
 -     bb5: {
-+     bb4: {
-          _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
--         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
+-         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
 -     }
 - 
 -     bb6: {
 -     }
 - 
 -     bb7: {
--         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
+-         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
 -     }
 - 
 -     bb8: {
++     bb4: {
+          _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
+-         goto -> bb9;                     // scope 0 at $DIR/simplify_cfg.rs:9:9: 11:10
+-     }
+- 
+-     bb9: {
           StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
 -         goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
 +         goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
       }
   
--     bb9: {
+-     bb10: {
 -         StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
 -         return;                          // scope 0 at $DIR/simplify_cfg.rs:13:2: 13:2
 -     }
 - 
--     bb10 (cleanup): {
+-     bb11 (cleanup): {
 +     bb5 (cleanup): {
           resume;                          // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
       }
index b6ce74d72898ab1816ee4500c7a00d464d0c0244..def6f835131c941bdcee89feceb274177384b583 100644 (file)
@@ -9,26 +9,26 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
           _1 = const false;                // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
--         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
-+         goto -> bb2;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
+-         switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
++         goto -> bb3;                     // scope 0 at $DIR/simplify_if.rs:6:8: 6:13
       }
   
       bb1: {
           StorageLive(_2);                 // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
-          _2 = noop() -> bb3;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
+          _2 = noop() -> bb2;              // scope 0 at $DIR/simplify_if.rs:7:9: 7:15
                                            // mir::Constant
                                            // + span: $DIR/simplify_if.rs:7:9: 7:13
                                            // + literal: Const { ty: fn() {noop}, val: Value(Scalar(<ZST>)) }
       }
   
       bb2: {
-          nop;                             // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:7:15: 7:16
+          nop;                             // scope 0 at $DIR/simplify_if.rs:6:14: 8:6
           goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
       }
   
       bb3: {
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_if.rs:7:15: 7:16
-          nop;                             // scope 0 at $DIR/simplify_if.rs:6:14: 8:6
+          nop;                             // scope 0 at $DIR/simplify_if.rs:8:6: 8:6
           goto -> bb4;                     // scope 0 at $DIR/simplify_if.rs:6:5: 8:6
       }
   
index 41a6fe30412d028e2ef6c2efdf0ebd3e9ad66f1a..fdd838f9a90793eab4f8ffaa744eba35d04b43c1 100644 (file)
           (_1.1: std::option::Option<T>) = move _3; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:30: 4:69
           StorageDead(_3);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:68: 4:69
           StorageDead(_2);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:68: 4:69
-          _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:13: 4:20
-          switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:13: 4:20
+          _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:12: 4:27
+          switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:12: 4:27
       }
   
       bb1: {
-          _4 = discriminant((_1.1: std::option::Option<T>)); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:22: 4:26
-          switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:22: 4:26
+          _4 = discriminant((_1.1: std::option::Option<T>)); // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:12: 4:27
+          switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:12: 4:27
       }
   
       bb2: {
 -         _7 = Gt(move _8, const 42_u8);   // scope 0 at $DIR/simplify-locals-fixedpoint.rs:5:12: 5:20
 -         StorageDead(_8);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:5:19: 5:20
 -         StorageDead(_7);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:7:9: 7:10
+          StorageDead(_6);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:8:5: 8:6
           goto -> bb3;                     // scope 0 at $DIR/simplify-locals-fixedpoint.rs:4:5: 8:6
       }
   
       bb3: {
-          StorageDead(_6);                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:8:5: 8:6
           drop(_1) -> bb4;                 // scope 0 at $DIR/simplify-locals-fixedpoint.rs:9:1: 9:2
       }
   
index 760fb747f7229aac41b6abb9cb2db08c3720c3fe..e139eedf3a0d627df07506ee1c9334e7f35fa080 100644 (file)
@@ -15,9 +15,9 @@
       }
   
       bb0: {
--         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
--         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
--         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
+-         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
           _0 = move _1;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:20: 6:27
 -         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:8:1: 8:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:8:2: 8:2
index 760fb747f7229aac41b6abb9cb2db08c3720c3fe..e139eedf3a0d627df07506ee1c9334e7f35fa080 100644 (file)
@@ -15,9 +15,9 @@
       }
   
       bb0: {
--         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
--         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
--         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:5:9: 5:13
+-         _5 = const false;                // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
+-         _5 = const true;                 // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
+-         _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:11: 4:12
           _0 = move _1;                    // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:20: 6:27
 -         _6 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:8:1: 8:2
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:8:2: 8:2
index 3f5efcffc19957b7ace93bc920e682856f82753b..1c8d043a6030c54a8d66762a6b655e4f7883694c 100644 (file)
 -         _1 = _2;                         // scope 1 at $DIR/simplify_match.rs:6:28: 6:29
 +         _1 = const false;                // scope 1 at $DIR/simplify_match.rs:6:28: 6:29
           StorageDead(_2);                 // scope 0 at $DIR/simplify_match.rs:6:30: 6:31
--         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
-+         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:7:9: 7:13
+-         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:6:5: 6:31
++         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:6:5: 6:31
       }
   
       bb1: {
           nop;                             // scope 0 at $DIR/simplify_match.rs:8:18: 8:20
-          goto -> bb3;                     // scope 0 at $DIR/simplify_match.rs:6:5: 9:6
+          goto -> bb3;                     // scope 0 at $DIR/simplify_match.rs:8:18: 8:20
       }
   
       bb2: {
index e09b8cb39bd510bb06c97949d336ce2ac98fe508..a6ea8cacfd2c5c375504c21e27e375baa6473beb 100644 (file)
 -         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
 -         _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
 -         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
--         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
 +         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
 +         nop;                             // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
-+         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
-          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:21:13: 21:33
       }
   
       bb1: {
index 488ad33f80a2dc2ae2206179643924cd9d3760a4..bef57548005ceee088373935c87fc62b53dbf0f7 100644 (file)
@@ -45,8 +45,8 @@
           _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
           _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
           StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:21:13: 21:33
       }
   
       bb1: {
index 5d829f859e9d9afafe5a9f959f349f59fb7a7fa8..aa19c479881aa83a98b42e6e719e88833a36b62f 100644 (file)
@@ -39,8 +39,8 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
         _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
-        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
-        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:21:13: 21:33
     }
 
     bb1: {
index 17dcc99bc0c6f9a4409b798ee45b0234eaded96c..bdcb9357308ec26fc7619b396b978e773f0be622 100644 (file)
@@ -16,7 +16,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6
         StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
         discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
-        _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20
+        _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
         StorageLive(_5);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24
         _5 = const "C";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24
                                          // ty::Const
@@ -32,8 +32,8 @@ fn main() -> () {
         StorageLive(_6);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
         StorageLive(_7);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
         discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
-        _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17
-        switchInt(move _8) -> [4_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17
+        _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
+        switchInt(move _8) -> [4_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 26:19
     }
 
     bb1: {
@@ -47,7 +47,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
         _6 = &(*_9);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24
         StorageDead(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24
-        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
+        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24
     }
 
     bb2: {
@@ -58,7 +58,7 @@ fn main() -> () {
                                          // mir::Constant
                                          // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
-        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
+        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24
     }
 
     bb3: {
index 9ae7a9d7384c150af7fe4c0a4e019882da5023bf..d8410caa7cd5621c524798a1af49fcc518762913 100644 (file)
@@ -17,9 +17,9 @@
           StorageLive(_1);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6
           StorageLive(_2);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
           discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
-          _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20
--         switchInt(move _3) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20
-+         switchInt(move _3) -> bb1;       // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20
+          _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19
+-         switchInt(move _3) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 20:19
++         switchInt(move _3) -> bb1;       // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 20:19
       }
   
       bb1: {
@@ -33,7 +33,7 @@
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _1 = &(*_5);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24
           StorageDead(_5);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6
+          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:23:23: 23:24
       }
   
       bb2: {
@@ -44,7 +44,7 @@
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching.rs:21:24: 21:34
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6
+          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34
       }
   
       bb3: {
@@ -58,7 +58,7 @@
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
           _1 = &(*_4);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34
           StorageDead(_4);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6
+          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:22:33: 22:34
       }
   
       bb4: {
@@ -67,8 +67,8 @@
           StorageLive(_6);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
           StorageLive(_7);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
           discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
-          _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17
-          switchInt(move _8) -> [4_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17
+          _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19
+          switchInt(move _8) -> [4_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 26:19
       }
   
       bb5: {
@@ -82,7 +82,7 @@
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _6 = &(*_9);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24
           StorageDead(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24
-          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
+          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:28:23: 28:24
       }
   
       bb6: {
@@ -93,7 +93,7 @@
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
-          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6
+          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24
       }
   
       bb7: {
index 373be9f174b2d2514e00a713f21db5229a16e75b..e20faa52474991f1039ae003c6dd13912de7d54d 100644 (file)
@@ -29,8 +29,8 @@ fn main() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
         StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
         _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
-        _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
-        switchInt(move _5) -> [2_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+        _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+        switchInt(move _5) -> [2_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 21:22
     }
 
     bb1: {
@@ -44,7 +44,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
         _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
         StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
-        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
     }
 
     bb2: {
@@ -58,15 +58,15 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
         _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
         StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
-        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
     }
 
     bb3: {
         StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
         StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
         StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
-        _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
-        switchInt(move _10) -> [2_isize: bb5, otherwise: bb4]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+        _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:11: 28:21
+        switchInt(move _10) -> [2_isize: bb5, otherwise: bb4]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 28:21
     }
 
     bb4: {
@@ -80,7 +80,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
         _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
         StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
-        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
     }
 
     bb5: {
@@ -94,7 +94,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
         _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
         StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
-        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
     }
 
     bb6: {
index f9488bae4c836ee341812a7ec1841a467e8c6fb4..77507ef1ee02dcaafc90f7d03ccd88f4dee112a4 100644 (file)
@@ -30,9 +30,9 @@
           StorageLive(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
           StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
           _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
-          _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
--         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
-+         switchInt(move _5) -> [2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:9: 22:20
+          _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:11: 21:22
+-         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 21:22
++         switchInt(move _5) -> [2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 21:22
       }
   
       bb1: {
@@ -46,7 +46,7 @@
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24
           StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:23: 25:24
       }
   
       bb2: {
@@ -57,7 +57,7 @@
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34
       }
   
       bb3: {
@@ -71,7 +71,7 @@
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
           _3 = &(*_6);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34
           StorageDead(_6);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:33: 23:34
       }
   
       bb4: {
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24
           StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:21:5: 26:6
+          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:23: 24:24
       }
   
       bb5: {
           StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
           StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:26:6: 26:7
           StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
-          _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
--         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb8, 2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
-+         switchInt(move _10) -> [2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:9: 29:20
+          _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:11: 28:21
+-         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb8, 2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 28:21
++         switchInt(move _10) -> [2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 28:21
       }
   
       bb6: {
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24
           StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:23: 32:24
       }
   
       bb7: {
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34
       }
   
       bb8: {
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) }
           _9 = &(*_11);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34
           StorageDead(_11);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:33: 30:34
       }
   
       bb9: {
                                            // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) }
           _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24
           StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:28:5: 33:6
+          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:23: 31:24
       }
   
       bb10: {
index ff05951a99b6343e3a38636a08365d312a594d7d..63356a400d29aa519fa7692796aa9974fb1e44a3 100644 (file)
   
       bb1: {
           _2 = discriminant(_1);           // scope 0 at $DIR/unreachable.rs:9:12: 9:20
--         switchInt(move _2) -> [1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/unreachable.rs:9:12: 9:20
+-         switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable.rs:9:12: 9:20
 +         goto -> bb2;                     // scope 0 at $DIR/unreachable.rs:9:12: 9:20
       }
   
       bb2: {
-          _0 = const ();                   // scope 0 at $DIR/unreachable.rs:19:6: 19:6
-          StorageDead(_3);                 // scope 0 at $DIR/unreachable.rs:19:5: 19:6
-          StorageDead(_1);                 // scope 0 at $DIR/unreachable.rs:20:1: 20:2
-          return;                          // scope 0 at $DIR/unreachable.rs:20:2: 20:2
--     }
-- 
--     bb3: {
 -         StorageLive(_3);                 // scope 0 at $DIR/unreachable.rs:9:17: 9:19
 -         _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable.rs:9:17: 9:19
 -         StorageLive(_4);                 // scope 0 at $DIR/unreachable.rs:10:13: 10:19
 -         StorageLive(_5);                 // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -         StorageLive(_6);                 // scope 2 at $DIR/unreachable.rs:12:12: 12:16
 -         _6 = const true;                 // scope 2 at $DIR/unreachable.rs:12:12: 12:16
--         switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable.rs:12:9: 16:10
+-         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:12:12: 12:16
 -     }
 - 
--     bb4: {
+-     bb3: {
 -         _4 = const 21_i32;               // scope 2 at $DIR/unreachable.rs:13:13: 13:20
 -         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:12:17: 14:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
+-         goto -> bb5;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -     }
 - 
--     bb5: {
+-     bb4: {
 -         _4 = const 42_i32;               // scope 2 at $DIR/unreachable.rs:15:13: 15:20
 -         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:14:16: 16:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
+-         goto -> bb5;                     // scope 2 at $DIR/unreachable.rs:12:9: 16:10
 -     }
 - 
--     bb6: {
+-     bb5: {
 -         StorageDead(_6);                 // scope 2 at $DIR/unreachable.rs:16:9: 16:10
 -         StorageDead(_5);                 // scope 2 at $DIR/unreachable.rs:16:9: 16:10
 -         StorageLive(_7);                 // scope 2 at $DIR/unreachable.rs:18:9: 18:21
 -         unreachable;                     // scope 2 at $DIR/unreachable.rs:18:15: 18:17
+-     }
+- 
+-     bb6: {
+          _0 = const ();                   // scope 0 at $DIR/unreachable.rs:19:6: 19:6
+          StorageDead(_1);                 // scope 0 at $DIR/unreachable.rs:20:1: 20:2
+          return;                          // scope 0 at $DIR/unreachable.rs:20:2: 20:2
       }
   }
   
index b94441d59195de902e71b5c7c52ef8ba4c8b39c1..09eb210f36873a116b48c33f1ef34c76b2135006 100644 (file)
   
       bb1: {
           _2 = discriminant(_1);           // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20
-          switchInt(move _2) -> [1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20
+          switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable_asm.rs:11:12: 11:20
       }
   
       bb2: {
-          _0 = const ();                   // scope 0 at $DIR/unreachable_asm.rs:23:6: 23:6
-          StorageDead(_3);                 // scope 0 at $DIR/unreachable_asm.rs:23:5: 23:6
-          StorageDead(_1);                 // scope 0 at $DIR/unreachable_asm.rs:24:1: 24:2
-          return;                          // scope 0 at $DIR/unreachable_asm.rs:24:2: 24:2
-      }
-  
-      bb3: {
           StorageLive(_3);                 // scope 0 at $DIR/unreachable_asm.rs:11:17: 11:19
           _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable_asm.rs:11:17: 11:19
           StorageLive(_4);                 // scope 0 at $DIR/unreachable_asm.rs:12:13: 12:19
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16
           _6 = const true;                 // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16
-          switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
+          switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_asm.rs:14:12: 14:16
       }
   
-      bb4: {
+      bb3: {
           _4 = const 21_i32;               // scope 2 at $DIR/unreachable_asm.rs:15:13: 15:20
           _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:14:17: 16:10
-          goto -> bb6;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
+          goto -> bb5;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
       }
   
-      bb5: {
+      bb4: {
           _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm.rs:17:13: 17:20
           _5 = const ();                   // scope 2 at $DIR/unreachable_asm.rs:16:16: 18:10
-          goto -> bb6;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
+          goto -> bb5;                     // scope 2 at $DIR/unreachable_asm.rs:14:9: 18:10
       }
   
-      bb6: {
+      bb5: {
           StorageDead(_6);                 // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10
           StorageDead(_5);                 // scope 2 at $DIR/unreachable_asm.rs:18:9: 18:10
           StorageLive(_7);                 // scope 2 at $DIR/unreachable_asm.rs:21:9: 21:37
           StorageLive(_8);                 // scope 2 at $DIR/unreachable_asm.rs:22:9: 22:21
           unreachable;                     // scope 2 at $DIR/unreachable_asm.rs:22:15: 22:17
       }
+  
+      bb6: {
+          _0 = const ();                   // scope 0 at $DIR/unreachable_asm.rs:23:6: 23:6
+          StorageDead(_1);                 // scope 0 at $DIR/unreachable_asm.rs:24:1: 24:2
+          return;                          // scope 0 at $DIR/unreachable_asm.rs:24:2: 24:2
+      }
   }
   
index 666843eab3d09ae074f6074124dd6854468cc6e6..cdb28ca12cc7ffcbdf8dd63f07580026cbdab0c8 100644 (file)
   
       bb1: {
           _2 = discriminant(_1);           // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20
-          switchInt(move _2) -> [1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20
+-         switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20
++         switchInt(move _2) -> [1_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/unreachable_asm_2.rs:11:12: 11:20
       }
   
       bb2: {
-          _0 = const ();                   // scope 0 at $DIR/unreachable_asm_2.rs:25:6: 25:6
-          StorageDead(_3);                 // scope 0 at $DIR/unreachable_asm_2.rs:25:5: 25:6
-          StorageDead(_1);                 // scope 0 at $DIR/unreachable_asm_2.rs:26:1: 26:2
-          return;                          // scope 0 at $DIR/unreachable_asm_2.rs:26:2: 26:2
-      }
-  
-      bb3: {
           StorageLive(_3);                 // scope 0 at $DIR/unreachable_asm_2.rs:11:17: 11:19
           _3 = move ((_1 as Some).0: Empty); // scope 0 at $DIR/unreachable_asm_2.rs:11:17: 11:19
           StorageLive(_4);                 // scope 0 at $DIR/unreachable_asm_2.rs:12:13: 12:19
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16
           _6 = const true;                 // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16
-          switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+          switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_asm_2.rs:14:12: 14:16
       }
   
-      bb4: {
+      bb3: {
           StorageLive(_7);                 // scope 2 at $DIR/unreachable_asm_2.rs:16:13: 16:41
           llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 3 at $DIR/unreachable_asm_2.rs:16:22: 16:39
           _7 = const ();                   // scope 3 at $DIR/unreachable_asm_2.rs:16:13: 16:41
           StorageDead(_7);                 // scope 2 at $DIR/unreachable_asm_2.rs:16:40: 16:41
           _4 = const 21_i32;               // scope 2 at $DIR/unreachable_asm_2.rs:17:13: 17:20
           _5 = const ();                   // scope 2 at $DIR/unreachable_asm_2.rs:14:17: 18:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+-         goto -> bb5;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
 +         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
       }
   
-      bb5: {
+      bb4: {
           StorageLive(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:13: 20:41
           llvm_asm!(LlvmInlineAsmInner { asm: "NOP", asm_str_style: Cooked, outputs: [], inputs: [], clobbers: [], volatile: true, alignstack: false, dialect: Att } : [] : []); // scope 4 at $DIR/unreachable_asm_2.rs:20:22: 20:39
           _8 = const ();                   // scope 4 at $DIR/unreachable_asm_2.rs:20:13: 20:41
           StorageDead(_8);                 // scope 2 at $DIR/unreachable_asm_2.rs:20:40: 20:41
           _4 = const 42_i32;               // scope 2 at $DIR/unreachable_asm_2.rs:21:13: 21:20
           _5 = const ();                   // scope 2 at $DIR/unreachable_asm_2.rs:18:16: 22:10
--         goto -> bb6;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
--     }
-- 
--     bb6: {
+-         goto -> bb5;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
++         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+      }
+  
+      bb5: {
 -         StorageDead(_6);                 // scope 2 at $DIR/unreachable_asm_2.rs:22:9: 22:10
 -         StorageDead(_5);                 // scope 2 at $DIR/unreachable_asm_2.rs:22:9: 22:10
 -         StorageLive(_9);                 // scope 2 at $DIR/unreachable_asm_2.rs:24:9: 24:21
 -         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:24:15: 24:17
-+         unreachable;                     // scope 2 at $DIR/unreachable_asm_2.rs:14:9: 22:10
+-     }
+- 
+-     bb6: {
+          _0 = const ();                   // scope 0 at $DIR/unreachable_asm_2.rs:25:6: 25:6
+          StorageDead(_1);                 // scope 0 at $DIR/unreachable_asm_2.rs:26:1: 26:2
+          return;                          // scope 0 at $DIR/unreachable_asm_2.rs:26:2: 26:2
       }
   }
   
index 32a067f22453d00a7b316cc7265539400d8af52e..3e93ae7b1988792fdee5a59804188c8a32226b62 100644 (file)
   
       bb1: {
           _3 = discriminant(_2);           // scope 1 at $DIR/unreachable_diverging.rs:14:12: 14:22
-          switchInt(move _3) -> [1_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/unreachable_diverging.rs:14:12: 14:22
+-         switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable_diverging.rs:14:12: 14:22
++         switchInt(move _3) -> [1_isize: bb2, otherwise: bb5]; // scope 1 at $DIR/unreachable_diverging.rs:14:12: 14:22
       }
   
       bb2: {
-          _0 = const ();                   // scope 1 at $DIR/unreachable_diverging.rs:19:6: 19:6
-          StorageDead(_4);                 // scope 1 at $DIR/unreachable_diverging.rs:19:5: 19:6
-          StorageDead(_1);                 // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2
-          StorageDead(_2);                 // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2
-          return;                          // scope 0 at $DIR/unreachable_diverging.rs:20:2: 20:2
-      }
-  
-      bb3: {
           StorageLive(_4);                 // scope 1 at $DIR/unreachable_diverging.rs:14:17: 14:21
           _4 = move ((_2 as Some).0: Empty); // scope 1 at $DIR/unreachable_diverging.rs:14:17: 14:21
           StorageLive(_5);                 // scope 1 at $DIR/unreachable_diverging.rs:15:9: 17:10
           StorageLive(_6);                 // scope 1 at $DIR/unreachable_diverging.rs:15:12: 15:13
           _6 = _1;                         // scope 1 at $DIR/unreachable_diverging.rs:15:12: 15:13
--         switchInt(move _6) -> [false: bb5, otherwise: bb4]; // scope 1 at $DIR/unreachable_diverging.rs:15:9: 17:10
-+         goto -> bb4;                     // scope 1 at $DIR/unreachable_diverging.rs:15:9: 17:10
+-         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/unreachable_diverging.rs:15:12: 15:13
++         goto -> bb3;                     // scope 1 at $DIR/unreachable_diverging.rs:15:12: 15:13
       }
   
-      bb4: {
--         _5 = loop_forever() -> bb6;      // scope 1 at $DIR/unreachable_diverging.rs:16:13: 16:27
-+         _5 = loop_forever() -> bb5;      // scope 1 at $DIR/unreachable_diverging.rs:16:13: 16:27
+      bb3: {
+-         _5 = loop_forever() -> bb5;      // scope 1 at $DIR/unreachable_diverging.rs:16:13: 16:27
++         _5 = loop_forever() -> bb4;      // scope 1 at $DIR/unreachable_diverging.rs:16:13: 16:27
                                            // mir::Constant
                                            // + span: $DIR/unreachable_diverging.rs:16:13: 16:25
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value(Scalar(<ZST>)) }
       }
   
-      bb5: {
+      bb4: {
 -         _5 = const ();                   // scope 1 at $DIR/unreachable_diverging.rs:17:10: 17:10
--         goto -> bb6;                     // scope 1 at $DIR/unreachable_diverging.rs:15:9: 17:10
+-         goto -> bb5;                     // scope 1 at $DIR/unreachable_diverging.rs:15:9: 17:10
 -     }
 - 
--     bb6: {
+-     bb5: {
           StorageDead(_6);                 // scope 1 at $DIR/unreachable_diverging.rs:17:9: 17:10
           StorageDead(_5);                 // scope 1 at $DIR/unreachable_diverging.rs:17:9: 17:10
           StorageLive(_7);                 // scope 1 at $DIR/unreachable_diverging.rs:18:9: 18:22
           unreachable;                     // scope 1 at $DIR/unreachable_diverging.rs:18:15: 18:19
       }
+  
+-     bb6: {
++     bb5: {
+          _0 = const ();                   // scope 1 at $DIR/unreachable_diverging.rs:19:6: 19:6
+          StorageDead(_1);                 // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2
+          StorageDead(_2);                 // scope 0 at $DIR/unreachable_diverging.rs:20:1: 20:2
+          return;                          // scope 0 at $DIR/unreachable_diverging.rs:20:2: 20:2
+      }
   }
   
index 91927dc7f1676e6944fec1ecd24a3f58c0d35c7c..8ecda3a1ae2cba28acea5b76e63c1fd1b31fa5c1 100644 (file)
           StorageLive(_3);                 // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32
           discriminant(_3) = 0;            // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32
 -         _4 = discriminant(_3);           // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
--         switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
+-         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
 +         _4 = const 0_isize;              // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
-+         switchInt(const 0_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
++         switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
       }
   
       bb1: {
-          StorageLive(_7);                 // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
-          nop;                             // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
-          StorageDead(_7);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
-          goto -> bb4;                     // scope 1 at no-location
+          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb3, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:20: 7:24
-      }
-  
-      bb3: {
           _1 = const 1_i32;                // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15
           nop;                             // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
           goto -> bb4;                     // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
       }
   
+      bb3: {
+          StorageLive(_7);                 // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
+          nop;                             // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
+          StorageDead(_7);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
+          goto -> bb4;                     // scope 1 at no-location
+      }
+  
       bb4: {
           StorageDead(_3);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
           StorageDead(_1);                 // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2
index 91927dc7f1676e6944fec1ecd24a3f58c0d35c7c..8ecda3a1ae2cba28acea5b76e63c1fd1b31fa5c1 100644 (file)
           StorageLive(_3);                 // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32
           discriminant(_3) = 0;            // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32
 -         _4 = discriminant(_3);           // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
--         switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
+-         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
 +         _4 = const 0_isize;              // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
-+         switchInt(const 0_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
++         switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
       }
   
       bb1: {
-          StorageLive(_7);                 // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
-          nop;                             // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
-          StorageDead(_7);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
-          goto -> bb4;                     // scope 1 at no-location
+          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25
       }
   
       bb2: {
-          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb3, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:20: 7:24
-      }
-  
-      bb3: {
           _1 = const 1_i32;                // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15
           nop;                             // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
           goto -> bb4;                     // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14
       }
   
+      bb3: {
+          StorageLive(_7);                 // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
+          nop;                             // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6
+          StorageDead(_7);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
+          goto -> bb4;                     // scope 1 at no-location
+      }
+  
       bb4: {
           StorageDead(_3);                 // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6
           StorageDead(_1);                 // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2
index 325b8591c73388ba0339ebb29ad6171d338bab07..9db77d705ff99668492f892110e927a403185c26 100644 (file)
@@ -20,39 +20,39 @@ fn while_loop(_1: bool) -> () {
 
     bb1: {
         StorageDead(_3);                 // scope 0 at $DIR/while-storage.rs:10:21: 10:22
-        switchInt(move _2) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:5: 14:6
+        switchInt(move _2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
     }
 
     bb2: {
         StorageLive(_4);                 // scope 0 at $DIR/while-storage.rs:11:12: 11:23
         StorageLive(_5);                 // scope 0 at $DIR/while-storage.rs:11:21: 11:22
         _5 = _1;                         // scope 0 at $DIR/while-storage.rs:11:21: 11:22
-        _4 = get_bool(move _5) -> bb4;   // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+        _4 = get_bool(move _5) -> bb3;   // scope 0 at $DIR/while-storage.rs:11:12: 11:23
                                          // mir::Constant
                                          // + span: $DIR/while-storage.rs:11:12: 11:20
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
     }
 
     bb3: {
-        goto -> bb7;                     // scope 0 at no-location
-    }
-
-    bb4: {
         StorageDead(_5);                 // scope 0 at $DIR/while-storage.rs:11:22: 11:23
-        switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:9: 13:10
+        switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
     }
 
-    bb5: {
+    bb4: {
         StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:13:9: 13:10
         goto -> bb7;                     // scope 0 at no-location
     }
 
-    bb6: {
+    bb5: {
         StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:13:9: 13:10
         StorageDead(_2);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
         goto -> bb0;                     // scope 0 at $DIR/while-storage.rs:10:5: 14:6
     }
 
+    bb6: {
+        goto -> bb7;                     // scope 0 at no-location
+    }
+
     bb7: {
         StorageDead(_2);                 // scope 0 at $DIR/while-storage.rs:14:5: 14:6
         return;                          // scope 0 at $DIR/while-storage.rs:15:2: 15:2
index dab31cbf4ac9eef4770d4c4a0b292c5da3f0aa25..89636294035df53dcdd8167e3e0aa08982b18171 100644 (file)
    40|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
    41|      2|}
   ------------------
-  | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
   |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   41|      1|}
   ------------------
-  | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
+  | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
   |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
   |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
   |   41|      1|}
    46|      4|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
    47|      4|}
   ------------------
-  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
   |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   47|      2|}
   ------------------
-  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
+  | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
   |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
   |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
   |   47|      2|}
diff --git a/src/test/run-make-fulldeps/doctests-keep-binaries/Makefile b/src/test/run-make-fulldeps/doctests-keep-binaries/Makefile
new file mode 100644 (file)
index 0000000..273c898
--- /dev/null
@@ -0,0 +1,21 @@
+include ../../run-make-fulldeps/tools.mk
+
+# Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used.
+
+all: run no_run
+
+run:
+       mkdir -p $(TMPDIR)/doctests
+       $(RUSTC) --crate-type rlib t.rs
+       $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs
+       $(TMPDIR)/doctests/t_rs_2_0/rust_out
+       $(TMPDIR)/doctests/t_rs_8_0/rust_out
+       rm -rf $(TMPDIR)/doctests
+
+no_run:
+       mkdir -p $(TMPDIR)/doctests
+       $(RUSTC) --crate-type rlib t.rs
+       $(RUSTDOC) -Zunstable-options --test --persist-doctests $(TMPDIR)/doctests --extern t=$(TMPDIR)/libt.rlib t.rs --no-run
+       $(TMPDIR)/doctests/t_rs_2_0/rust_out
+       $(TMPDIR)/doctests/t_rs_8_0/rust_out
+       rm -rf $(TMPDIR)/doctests
diff --git a/src/test/run-make-fulldeps/doctests-keep-binaries/t.rs b/src/test/run-make-fulldeps/doctests-keep-binaries/t.rs
new file mode 100644 (file)
index 0000000..c38cf0a
--- /dev/null
@@ -0,0 +1,11 @@
+/// Fungle the foople.
+/// ```
+/// t::foople();
+/// ```
+pub fn foople() {}
+
+/// Flomble the florp
+/// ```
+/// t::florp();
+/// ```
+pub fn florp() {}
diff --git a/src/test/run-make-fulldeps/remap-path-prefix/Makefile b/src/test/run-make-fulldeps/remap-path-prefix/Makefile
new file mode 100644 (file)
index 0000000..86785c5
--- /dev/null
@@ -0,0 +1,9 @@
+-include ../tools.mk
+
+# ignore-windows
+
+# Checks if remapping works if the remap-from string contains path to the working directory plus more
+all:
+       $(RUSTC) --remap-path-prefix $$PWD/auxiliary=/the/aux --crate-type=lib --emit=metadata auxiliary/lib.rs
+       grep "/the/aux/lib.rs" $(TMPDIR)/liblib.rmeta || exit 1
+       ! grep "$$PWD/auxiliary" $(TMPDIR)/liblib.rmeta || exit 1
diff --git a/src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs b/src/test/run-make-fulldeps/remap-path-prefix/auxiliary/lib.rs
new file mode 100644 (file)
index 0000000..019c786
--- /dev/null
@@ -0,0 +1,3 @@
+pub fn lib() {
+    panic!("calm");
+}
diff --git a/src/test/run-make/incr-foreign-head-span/Makefile b/src/test/run-make/incr-foreign-head-span/Makefile
new file mode 100644 (file)
index 0000000..712965e
--- /dev/null
@@ -0,0 +1,21 @@
+include ../../run-make-fulldeps/tools.mk
+
+# ignore-none no-std is not supported
+# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for 'std'
+
+# Ensure that modifying a crate on disk (without recompiling it)
+# does not cause ICEs in downstream crates.
+# Previously, we would call `SourceMap.guess_head_span` on a span
+# from an external crate, which would cause us to read an upstream
+# source file from disk during compilation of a downstream crate
+# See #86480 for more details
+
+INCR=$(TMPDIR)/incr
+
+all:
+       cp first_crate.rs second_crate.rs $(TMPDIR)
+       $(RUSTC) $(TMPDIR)/first_crate.rs  -C incremental=$(INCR) --target $(TARGET) --crate-type lib
+       $(RUSTC) $(TMPDIR)/second_crate.rs -C incremental=$(INCR) --target $(TARGET)  --extern first-crate=$(TMPDIR) --crate-type lib
+       rm $(TMPDIR)/first_crate.rs
+       $(RUSTC) $(TMPDIR)/second_crate.rs  -C incremental=$(INCR) --target $(TARGET) --cfg second_run --crate-type lib
+
diff --git a/src/test/run-make/incr-foreign-head-span/first_crate.rs b/src/test/run-make/incr-foreign-head-span/first_crate.rs
new file mode 100644 (file)
index 0000000..69dd103
--- /dev/null
@@ -0,0 +1 @@
+pub trait OtherTrait {}
diff --git a/src/test/run-make/incr-foreign-head-span/second_crate.rs b/src/test/run-make/incr-foreign-head-span/second_crate.rs
new file mode 100644 (file)
index 0000000..102f6b2
--- /dev/null
@@ -0,0 +1,8 @@
+extern crate first_crate;
+use first_crate::OtherTrait;
+
+#[cfg(not(second_run))]
+trait Foo: OtherTrait {}
+
+#[cfg(second_run)]
+trait Bar: OtherTrait {}
index a9aad54162f110749cd45699c399452f27e61ed9..b8769d5f6905178c2aab86e27a20ef053a158ee2 100644 (file)
@@ -2,4 +2,3 @@
 
 all:
        $(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
-       $(RUSTC) --force-warn dead_code x.rs 2>&1 | diff - force-warn.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warn.stderr b/src/test/run-make/unstable-flag-required/force-warn.stderr
deleted file mode 100644 (file)
index 1b70dc8..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warn=lints`
-
diff --git a/src/test/run-make/wasm-spurious-import/Makefile b/src/test/run-make/wasm-spurious-import/Makefile
new file mode 100644 (file)
index 0000000..1bb59dc
--- /dev/null
@@ -0,0 +1,7 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-wasm32-bare
+
+all:
+       $(RUSTC) main.rs -C overflow-checks=yes -C panic=abort -C lto -C opt-level=z --target wasm32-unknown-unknown
+       $(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/src/test/run-make/wasm-spurious-import/main.rs b/src/test/run-make/wasm-spurious-import/main.rs
new file mode 100644 (file)
index 0000000..fcbead5
--- /dev/null
@@ -0,0 +1,14 @@
+#![crate_type = "cdylib"]
+#![no_std]
+
+#[panic_handler]
+fn my_panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+pub fn multer(a: i128, b: i128) -> i128 {
+    // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported
+    // panic function in case of a bug. We verify that no imports exist in our verifier.
+    a * b
+}
diff --git a/src/test/run-make/wasm-spurious-import/verify.js b/src/test/run-make/wasm-spurious-import/verify.js
new file mode 100644 (file)
index 0000000..d3b2101
--- /dev/null
@@ -0,0 +1,9 @@
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let imports = WebAssembly.Module.imports(m);
+console.log('imports', imports);
+assert.strictEqual(imports.length, 0);
diff --git a/src/test/rustdoc-gui/ayu-code-tag-colors.goml b/src/test/rustdoc-gui/ayu-code-tag-colors.goml
deleted file mode 100644 (file)
index 50af36f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to
-// check that the rule isn't applied on other "<code>" elements.
-goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html
-// We need to show the text, otherwise the colors aren't "computed" by the web browser.
-show-text: true
-// We set the theme to ayu.
-local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
-// We reload to get the text appearing and the theme applied.
-reload:
-
-assert-css: (".docblock code", {"color": "rgb(255, 180, 84)"}, ALL)
-// It includes variants and the "titles" as well (for example: "impl RefUnwindSafe for AnEnum").
-assert-css: ("div:not(.docblock) > code", {"color": "rgb(197, 197, 197)"}, ALL)
diff --git a/src/test/rustdoc-gui/code-color.goml b/src/test/rustdoc-gui/code-color.goml
new file mode 100644 (file)
index 0000000..2f95bfb
--- /dev/null
@@ -0,0 +1,30 @@
+// The ayu theme has a different color for the "<code>" tags in the doc blocks. We need to
+// check that the rule isn't applied on other "<code>" elements.
+//
+// While we're at it, we also check it for the other themes.
+goto: file://|DOC_PATH|/test_docs/fn.foo.html
+// If the text isn't displayed, the browser doesn't compute color style correctly...
+show-text: true
+// Set the theme to dark.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: (".docblock pre > code", {"color": "rgb(221, 221, 221)"}, ALL)
+assert-css: (".docblock > p > code", {"color": "rgb(221, 221, 221)"}, ALL)
+
+// Set the theme to ayu.
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: (".docblock pre > code", {"color": "rgb(230, 225, 207)"}, ALL)
+assert-css: (".docblock > p > code", {"color": "rgb(255, 180, 84)"}, ALL)
+
+// Set the theme to light.
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: (".docblock pre > code", {"color": "rgb(0, 0, 0)"}, ALL)
+assert-css: (".docblock > p > code", {"color": "rgb(0, 0, 0)"}, ALL)
index 92ad92a8c34155320f488a76b382d9af08a571a2..d8411511c5aeef97e3b01d7bc0e5406c8f433c67 100644 (file)
@@ -13,6 +13,21 @@ goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 assert-css: (".impl-items .method", {"font-weight": "600"}, ALL)
 
 goto: file://|DOC_PATH|/lib2/trait.Trait.html
+
+// This is a complex selector, so here's how it works:
+//
+// * //*[@class='docblock type-decl'] — selects element of any tag with classes docblock and type-decl
+// * /pre[@class='rust trait'] — selects immediate child with tag pre and classes rust and trait
+// * /code — selects immediate child with tag code
+// * /a[@class='constant'] — selects immediate child with tag a and class constant
+// * //text() — selects child that is text node
+// * /parent::* — selects immediate parent of the text node (the * means it can be any tag)
+//
+// This uses '/parent::*' as a proxy for the style of the text node.
+// We can't just select the '<a>' because intermediate tags could be added.
+assert-count: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", 1)
+assert-css: ("//*[@class='docblock type-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*", {"font-weight": "400"})
+
 assert-count: (".methods .type", 1)
 assert-css: (".methods .type", {"font-weight": "600"})
 assert-count: (".methods .constant", 1)
index 87e4f2a7bd141d158b8ce9e42637a922d244475e..c9042eb4813ab8a187dfb4969ddcb8bbb8d19a76 100644 (file)
@@ -3,14 +3,14 @@
 goto: file://|DOC_PATH|/implementors/trait.Whatever.html
 assert: "#implementors-list"
 // There are supposed to be two implementors listed.
-assert-count: ("#implementors-list .impl", 2)
+assert-count: ("#implementors-list .impl", 2)
 // Now we check that both implementors have an anchor, an ID and a similar DOM.
-assert: ("#implementors-list .impl:nth-child(1) > a.anchor")
-assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"})
-assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
-assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band"
+assert: ("#implementors-list .impl:nth-child(1) > a.anchor")
+assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"})
+assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
+assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band"
 
-assert: ("#implementors-list .impl:nth-child(2) > a.anchor")
-assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"})
-assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
-assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band"
+assert: ("#implementors-list .impl:nth-child(2) > a.anchor")
+assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"})
+assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
+assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band"
index 4b2f6962e30c50498ea7bdd381c8bbc77bc6c389..6417a6ac5af6de314d594cc47833508831e24a08 100644 (file)
@@ -1,7 +1,11 @@
 pub trait Whatever {
+    type Foo;
+
     fn method() {}
 }
 
 pub struct Struct;
 
-impl Whatever for Struct {}
+impl Whatever for Struct {
+    type Foo = u8;
+}
index 36373d24971c992a76d2532f0ff8dbad6ac29552..cb63a9f60022702881b01a86ac23d0299b5226f0 100644 (file)
@@ -38,7 +38,9 @@ impl Trait for Foo {
 }
 
 
-impl implementors::Whatever for Foo {}
+impl implementors::Whatever for Foo {
+    type Foo = u32;
+}
 
 pub mod sub_mod {
     /// ```txt
index bed72ccb9f929668f0b3388f2be52e6f00dbcf3e..af4f28047fc0d7b6e1bf50c4dab78f06ff2afca8 100644 (file)
@@ -25,6 +25,8 @@
 /// ```ignore (it's a test)
 /// Let's say I'm just some text will ya?
 /// ```
+///
+/// An inlined `code`!
 pub fn foo() {}
 
 /// Just a normal struct.
diff --git a/src/test/rustdoc-gui/toggle-implementors.goml b/src/test/rustdoc-gui/toggle-implementors.goml
new file mode 100644 (file)
index 0000000..15521ff
--- /dev/null
@@ -0,0 +1,4 @@
+// This test ensures that the implementors toggle are not open by default.
+goto: file://|DOC_PATH|/implementors/trait.Whatever.html
+
+assert-attribute-false: ("#implementors-list > details", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-json/enums/variant_struct.rs b/src/test/rustdoc-json/enums/variant_struct.rs
new file mode 100644 (file)
index 0000000..246e6a0
--- /dev/null
@@ -0,0 +1,11 @@
+// @has variant_struct.json "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\"
+pub enum EnumStruct {
+    // @has - "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\"
+    // @has - "$.index[*][?(@.name=='x')]"
+    // @has - "$.index[*][?(@.name=='y')]"
+    VariantS {
+        x: u32,
+        y: String,
+    },
+}
diff --git a/src/test/rustdoc-json/enums/variant_tuple_struct.rs b/src/test/rustdoc-json/enums/variant_tuple_struct.rs
new file mode 100644 (file)
index 0000000..d948dc5
--- /dev/null
@@ -0,0 +1,6 @@
+// @has variant_tuple_struct.json "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
+// @has - "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\"
+pub enum EnumTupleStruct {
+    // @has - "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\"
+    VariantA(u32, String),
+}
index ea98676863b5eed119ef38cd56561bb9950b02ea..9e64317ec203f9adc259366fac0427a8d99b2630 100644 (file)
@@ -1,7 +1,7 @@
 // @has with_primitives.json "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
-// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind" \"lifetime\"
+// @has - "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.struct_type" \"plain\"
 // @has - "$.index[*][?(@.name=='WithPrimitives')].inner.fields_stripped" true
 pub struct WithPrimitives<'a> {
diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.rs
new file mode 100644 (file)
index 0000000..3ad56ae
--- /dev/null
@@ -0,0 +1,17 @@
+// This test ensures that rustdoc does not panic on inherented associated types
+// that are referred to without fully-qualified syntax.
+
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+pub struct Struct;
+
+impl Struct {
+    pub type AssocTy = usize;
+    pub const AssocConst: Self::AssocTy = 42;
+    //~^ ERROR ambiguous associated type
+    //~| HELP use fully-qualified syntax
+    // FIXME: for some reason, the error is shown twice with rustdoc but only once with rustc
+    //~| ERROR ambiguous associated type
+    //~| HELP use fully-qualified syntax
+}
diff --git a/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr b/src/test/rustdoc-ui/ambiguous-inherent-assoc-ty.stderr
new file mode 100644 (file)
index 0000000..b963b72
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
+   |
+LL |     pub const AssocConst: Self::AssocTy = 42;
+   |                           ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/ambiguous-inherent-assoc-ty.rs:11:27
+   |
+LL |     pub const AssocConst: Self::AssocTy = 42;
+   |                           ^^^^^^^^^^^^^ help: use fully-qualified syntax: `<Struct as Trait>::AssocTy`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/rustdoc-ui/auxiliary/panic-item.rs b/src/test/rustdoc-ui/auxiliary/panic-item.rs
new file mode 100644 (file)
index 0000000..17b2685
--- /dev/null
@@ -0,0 +1,17 @@
+// no-prefer-dynamic
+#![crate_type = "lib"]
+#![no_std]
+#![feature(lang_items)]
+
+use core::panic::PanicInfo;
+use core::sync::atomic::{self, Ordering};
+
+#[panic_handler]
+fn panic(_info: &PanicInfo) -> ! {
+    loop {
+        atomic::compiler_fence(Ordering::SeqCst);
+    }
+}
+
+#[lang = "eh_personality"]
+fn foo() {}
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.rs b/src/test/rustdoc-ui/bounded-hr-lifetime.rs
new file mode 100644 (file)
index 0000000..b2e000b
--- /dev/null
@@ -0,0 +1,9 @@
+// This test ensures that rustdoc doesn't panic on higher-ranked lifetimes
+// with bounds, because an error should have already been emitted by rustc.
+
+pub fn hrlt<'b, 'c>()
+where
+    for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+    //~^ ERROR lifetime bounds cannot be used in this context
+{
+}
diff --git a/src/test/rustdoc-ui/bounded-hr-lifetime.stderr b/src/test/rustdoc-ui/bounded-hr-lifetime.stderr
new file mode 100644 (file)
index 0000000..d8fcd6c
--- /dev/null
@@ -0,0 +1,10 @@
+error: lifetime bounds cannot be used in this context
+  --> $DIR/bounded-hr-lifetime.rs:6:13
+   |
+LL |     for<'a: 'b + 'c> &'a (): std::fmt::Debug,
+   |             ^^   ^^
+
+error: Compilation failed, aborting rustdoc
+
+error: aborting due to 2 previous errors
+
index a564006e74f4817259412c737691e90bc3492e5f..0867b08183e2de20eaa7af23ce9f43ce2c6e8b53 100644 (file)
@@ -1,4 +1,4 @@
-error: missing documentation for macro
+error: missing documentation for macro
   --> $DIR/deny-missing-docs-macro.rs:6:1
    |
 LL | macro_rules! foo {
diff --git a/src/test/rustdoc-ui/unused-extern-crate.rs b/src/test/rustdoc-ui/unused-extern-crate.rs
new file mode 100644 (file)
index 0000000..f703a18
--- /dev/null
@@ -0,0 +1,3 @@
+// check-pass
+// aux-crate:panic_item=panic-item.rs
+// @has unused_extern_crate/index.html
diff --git a/src/test/rustdoc/auxiliary/issue-66159-1.rs b/src/test/rustdoc/auxiliary/issue-66159-1.rs
deleted file mode 100644 (file)
index 2f3d069..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/// This will be referred to by the test docstring
-pub struct Something;
index 123dbaa406b83eeb8fe5eba1ee6832736c4abdc5..7e38eb8369a8a7bbded402663945ec8d0d65cd8a 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(const_generics)]
 #![crate_name = "foo"]
 
 use std::ops::Add;
diff --git a/src/test/rustdoc/const-generics/const-evaluatable-checked.rs b/src/test/rustdoc/const-generics/const-evaluatable-checked.rs
deleted file mode 100644 (file)
index 1c074fd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![crate_name = "foo"]
-#![feature(const_evaluatable_checked, const_generics)]
-#![allow(incomplete_features)]
-// make sure that `ConstEvaluatable` predicates dont cause rustdoc to ICE #77647
-// @has foo/struct.Ice.html '//pre[@class="rust struct"]' \
-//      'pub struct Ice<const N: usize> where [(); N + 1]: ;'
-pub struct Ice<const N: usize> where [(); N + 1]:;
index 626a9e2b2109e86b03c9b5d3f87c15ad0667fc8a..b20663c6d68a5736e252d9baba89e6fa611c6f50 100644 (file)
@@ -1,5 +1,4 @@
 #![crate_name = "foo"]
-#![feature(const_generics)]
 
 pub trait Array {
     type Item;
index 7ddcb3a29f28b21c7c44c9bebc1e53706d001897..fed37f6c9a2d55849f8c5db1f4fbf907579c2aa2 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 
 #![crate_name = "foo"]
 
diff --git a/src/test/rustdoc/const-generics/generic_const_exprs.rs b/src/test/rustdoc/const-generics/generic_const_exprs.rs
new file mode 100644 (file)
index 0000000..35036a8
--- /dev/null
@@ -0,0 +1,7 @@
+#![crate_name = "foo"]
+#![feature(generic_const_exprs)]
+#![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> where [(); N + 1]:;
index f4c5dcc72259d3e6e6f4424e195a9aef6d799b68..4eac8e31e45292ea5d950aefc349215c697b39f3 100644 (file)
@@ -1,5 +1,5 @@
 #![crate_name = "foo"]
-#![feature(lazy_normalization_consts)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate,
diff --git a/src/test/rustdoc/intra-doc/auxiliary/pub-struct.rs b/src/test/rustdoc/intra-doc/auxiliary/pub-struct.rs
new file mode 100644 (file)
index 0000000..75d4289
--- /dev/null
@@ -0,0 +1 @@
+pub struct SomeStruct;
diff --git a/src/test/rustdoc/intra-doc/extern-reference-link.rs b/src/test/rustdoc/intra-doc/extern-reference-link.rs
new file mode 100644 (file)
index 0000000..bad6ec7
--- /dev/null
@@ -0,0 +1,7 @@
+// compile-flags: --extern pub_struct
+// aux-build:pub-struct.rs
+
+/// [SomeStruct]
+///
+/// [SomeStruct]: pub_struct::SomeStruct
+pub fn foo() {}
diff --git a/src/test/rustdoc/intra-doc/issue-66159.rs b/src/test/rustdoc/intra-doc/issue-66159.rs
new file mode 100644 (file)
index 0000000..56742b3
--- /dev/null
@@ -0,0 +1,10 @@
+// aux-crate:priv:pub_struct=pub-struct.rs
+// compile-flags:-Z unstable-options
+
+// The issue was an ICE which meant that we never actually generated the docs
+// so if we have generated the docs, we're okay.
+// Since we don't generate the docs for the auxiliary files, we can't actually
+// verify that the struct is linked correctly.
+
+// @has issue_66159/index.html
+//! [pub_struct::SomeStruct]
diff --git a/src/test/rustdoc/issue-66159.rs b/src/test/rustdoc/issue-66159.rs
deleted file mode 100644 (file)
index 003d079..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// aux-crate:priv:issue_66159_1=issue-66159-1.rs
-// compile-flags:-Z unstable-options
-
-// The issue was an ICE which meant that we never actually generated the docs
-// so if we have generated the docs, we're okay.
-// Since we don't generate the docs for the auxiliary files, we can't actually
-// verify that the struct is linked correctly.
-
-// @has issue_66159/index.html
-//! [issue_66159_1::Something]
diff --git a/src/test/rustdoc/macro-document-private-duplicate.rs b/src/test/rustdoc/macro-document-private-duplicate.rs
new file mode 100644 (file)
index 0000000..460785e
--- /dev/null
@@ -0,0 +1,23 @@
+// FIXME: If two macros in the same module have the same name
+// (yes, that's a thing), rustdoc lists both of them on the index page,
+// but only documents the first one on the page for the macro.
+// Fortunately, this can only happen in document private items mode,
+// but it still isn't ideal beahvior.
+//
+// See https://github.com/rust-lang/rust/pull/88019#discussion_r693920453
+//
+// compile-flags: --document-private-items
+
+// @has macro_document_private_duplicate/index.html 'Doc 1.'
+// @has macro_document_private_duplicate/macro.a_macro.html 'Doc 1.'
+/// Doc 1.
+macro_rules! a_macro {
+    () => ()
+}
+
+// @has macro_document_private_duplicate/index.html 'Doc 2.'
+// @!has macro_document_private_duplicate/macro.a_macro.html 'Doc 2.'
+/// Doc 2.
+macro_rules! a_macro {
+    () => ()
+}
diff --git a/src/test/rustdoc/macro-document-private.rs b/src/test/rustdoc/macro-document-private.rs
new file mode 100644 (file)
index 0000000..d249691
--- /dev/null
@@ -0,0 +1,19 @@
+// Checks that private macros are documented when `--document-private-items`
+// is present.
+//
+// This is a regression test for issue #73754.
+//
+// compile-flags: --document-private-items
+
+#![feature(decl_macro)]
+
+
+// @has macro_document_private/macro.some_macro.html
+macro some_macro {
+    (a: tt) => {}
+}
+
+// @has macro_document_private/macro.another_macro.html
+macro_rules! another_macro {
+    (a: tt) => {}
+}
diff --git a/src/test/rustdoc/macro-indirect-use.rs b/src/test/rustdoc/macro-indirect-use.rs
new file mode 100644 (file)
index 0000000..b2d9336
--- /dev/null
@@ -0,0 +1,16 @@
+// Checks that it is possible to make a macro public through a `pub use` of its
+// parent module.
+//
+// This is a regression test for issue #87257.
+
+#![feature(decl_macro)]
+
+mod outer {
+    pub mod inner {
+        pub macro some_macro() {}
+    }
+}
+
+// @has macro_indirect_use/inner/index.html
+// @has macro_indirect_use/inner/macro.some_macro.html
+pub use outer::inner;
diff --git a/src/test/rustdoc/macro-private-not-documented.rs b/src/test/rustdoc/macro-private-not-documented.rs
new file mode 100644 (file)
index 0000000..ae8b0e7
--- /dev/null
@@ -0,0 +1,19 @@
+// Checks that private macros aren't documented by default. They
+// should be still be documented in `--document-private-items` mode,
+// but that's tested in `macro-document-private.rs`.
+//
+//
+// This is a regression text for issue #88453.
+#![feature(decl_macro)]
+
+// @!has macro_private_not_documented/index.html 'a_macro'
+// @!has macro_private_not_documented/macro.a_macro.html
+macro_rules! a_macro {
+    () => ()
+}
+
+// @!has macro_private_not_documented/index.html 'another_macro'
+// @!has macro_private_not_documented/macro.another_macro.html
+macro another_macro {
+    () => ()
+}
index ddbe93febdc2526a9306312f790a1f07d7b0e04e..4d25835bf08fd231d479e4306ac9a3ed7af15af6 100644 (file)
@@ -1,6 +1,6 @@
 pub trait MyTrait {
     type Assoc;
-    const VALUE: u32;
+    const VALUE: u32 = 12;
     fn trait_function(&self);
     fn defaulted(&self) {}
     fn defaulted_override(&self) {}
@@ -38,9 +38,11 @@ fn defaulted_override(&self) {}
 }
 
 impl MyTrait for MyStruct {
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc
     type Assoc = bool;
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE
     // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE
     const VALUE: u32 = 20;
@@ -55,3 +57,10 @@ fn defaulted_override(&self) {}
 }
 
 pub struct MyStruct;
+
+// We check that associated items with default values aren't generated in the implementors list.
+impl MyTrait for (u8, u8) {
+    // @!has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-4"]'
+    type Assoc = bool;
+    fn trait_function(&self) {}
+}
diff --git a/src/test/rustfix/closure-immutable-outer-variable.fixed b/src/test/rustfix/closure-immutable-outer-variable.fixed
deleted file mode 100644 (file)
index 05bbc13..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Point at the captured immutable outer variable
-
-fn foo(mut f: Box<FnMut()>) {
-    f();
-}
-
-fn main() {
-    let mut y = true;
-    foo(Box::new(move || y = false) as Box<_>);
-}
diff --git a/src/test/rustfix/closure-immutable-outer-variable.rs b/src/test/rustfix/closure-immutable-outer-variable.rs
deleted file mode 100644 (file)
index 6ed1bc1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Point at the captured immutable outer variable
-
-fn foo(mut f: Box<FnMut()>) {
-    f();
-}
-
-fn main() {
-    let y = true;
-    foo(Box::new(move || y = false) as Box<_>);
-}
diff --git a/src/test/rustfix/empty-no-fixes.fixed b/src/test/rustfix/empty-no-fixes.fixed
deleted file mode 100644 (file)
index 3724a00..0000000
+++ /dev/null
@@ -1 +0,0 @@
-// compile-flags:--crate-type lib
diff --git a/src/test/rustfix/empty-no-fixes.rs b/src/test/rustfix/empty-no-fixes.rs
deleted file mode 100644 (file)
index 3724a00..0000000
+++ /dev/null
@@ -1 +0,0 @@
-// compile-flags:--crate-type lib
diff --git a/src/test/rustfix/empty-no-fixes.rs.fixed b/src/test/rustfix/empty-no-fixes.rs.fixed
deleted file mode 100644 (file)
index e30d3ae..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-// compile-flags:--crate-type lib
-fn foo() {}
diff --git a/src/test/rustfix/issue-45562.fixed b/src/test/rustfix/issue-45562.fixed
deleted file mode 100644 (file)
index 955b2cb..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#[no_mangle] pub static RAH: usize = 5;
-
-fn main() {}
diff --git a/src/test/rustfix/issue-45562.rs b/src/test/rustfix/issue-45562.rs
deleted file mode 100644 (file)
index a1ac070..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#[no_mangle] pub const RAH: usize = 5;
-
-fn main() {}
diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
deleted file mode 100644 (file)
index b4ae4dc..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-extern crate std as other_std;
-fn main() {}
diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
deleted file mode 100644 (file)
index a202b6c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-extern crate std;
-fn main() {}
diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed
deleted file mode 100644 (file)
index bedc8e1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![allow(unused)]
-
-fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
-    and_yet + 1
-}
-
-fn main() {
-    let behold: isize = 2;
-    let with_tears: usize = 3;
-    light_flows_our_war_of_mocking_words(&(behold as usize));
-    light_flows_our_war_of_mocking_words(&(with_tears + 4));
-}
diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs
deleted file mode 100644 (file)
index 9c7ae96..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#![allow(unused)]
-
-fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize {
-    and_yet + 1
-}
-
-fn main() {
-    let behold: isize = 2;
-    let with_tears: usize = 3;
-    light_flows_our_war_of_mocking_words(behold as usize);
-    light_flows_our_war_of_mocking_words(with_tears + 4);
-}
diff --git a/src/test/rustfix/main-no-fixes.fixed b/src/test/rustfix/main-no-fixes.fixed
deleted file mode 100644 (file)
index f328e4d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-fn main() {}
diff --git a/src/test/rustfix/main-no-fixes.rs b/src/test/rustfix/main-no-fixes.rs
deleted file mode 100644 (file)
index f328e4d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-fn main() {}
diff --git a/src/test/rustfix/main-no-fixes.rs.fixed b/src/test/rustfix/main-no-fixes.rs.fixed
deleted file mode 100644 (file)
index f328e4d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-fn main() {}
diff --git a/src/test/rustfix/missing-comma-in-match.fixed b/src/test/rustfix/missing-comma-in-match.fixed
deleted file mode 100644 (file)
index d4696ab..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    match &Some(3) {
-        &None => 1,
-        &Some(2) => { 3 }
-        _ => 2
-    };
-}
diff --git a/src/test/rustfix/missing-comma-in-match.rs b/src/test/rustfix/missing-comma-in-match.rs
deleted file mode 100644 (file)
index fed796c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    match &Some(3) {
-        &None => 1
-        &Some(2) => { 3 }
-        _ => 2
-    };
-}
diff --git a/src/test/rustfix/str-as-char.fixed b/src/test/rustfix/str-as-char.fixed
deleted file mode 100644 (file)
index 900fee9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!("●●");
-}
diff --git a/src/test/rustfix/str-as-char.rs b/src/test/rustfix/str-as-char.rs
deleted file mode 100644 (file)
index b446551..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    println!('●●');
-}
diff --git a/src/test/rustfix/tuple-float-index.fixed b/src/test/rustfix/tuple-float-index.fixed
deleted file mode 100644 (file)
index 358a27d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main () {
-    ((1, (2, 3)).1).1;
-}
diff --git a/src/test/rustfix/tuple-float-index.rs b/src/test/rustfix/tuple-float-index.rs
deleted file mode 100644 (file)
index 7261225..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main () {
-    (1, (2, 3)).1.1;
-}
index ed8e498b6b746ae0a1d813ea4b0f368e1952d4ab..8b0cebfa60e2c09251e99abcc6f30550c29fc343 100644 (file)
@@ -106,6 +106,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                     rules: BlockCheckMode::Default,
                     span: DUMMY_SP,
                     tokens: None,
+                    could_be_bare_literal: false,
                 });
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
             }
index 890174537592f91c56ea66e792814ea2d71d951a..225d49e05a3fa49fef67994992f726d6c772bbcf 100644 (file)
@@ -1,58 +1,64 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:24:1
+  --> $DIR/unsupported.rs:26:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:26:1
+  --> $DIR/unsupported.rs:28:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:28:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0570]: `"aapcs"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:32:1
+   |
+LL | extern "aapcs" fn aapcs() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:33:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:38:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:37:1
+  --> $DIR/unsupported.rs:40:1
    |
 LL | extern "x86-interrupt" fn x86() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:39:1
+  --> $DIR/unsupported.rs:43:1
    |
 LL | extern "stdcall" fn stdcall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(unsupported_calling_conventions)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:44:1
+  --> $DIR/unsupported.rs:50:1
    |
 LL | extern "thiscall" fn thiscall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to 7 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0570`.
diff --git a/src/test/ui/abi/unsupported.arm.stderr b/src/test/ui/abi/unsupported.arm.stderr
new file mode 100644 (file)
index 0000000..b050ee0
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:26:1
+   |
+LL | extern "ptx-kernel" fn ptx() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:28:1
+   |
+LL | extern "amdgpu-kernel" fn amdgpu() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"wasm"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:30:1
+   |
+LL | extern "wasm" fn wasm() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:36:1
+   |
+LL | extern "msp430-interrupt" fn msp430() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:38:1
+   |
+LL | extern "avr-interrupt" fn avr() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
+  --> $DIR/unsupported.rs:40:1
+   |
+LL | extern "x86-interrupt" fn x86() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:43:1
+   |
+LL | extern "stdcall" fn stdcall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unsupported_calling_conventions)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+warning: use of calling convention not supported on this target
+  --> $DIR/unsupported.rs:50:1
+   |
+LL | extern "thiscall" fn thiscall() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+
+error: aborting due to 6 previous errors; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0570`.
index 81b12653d2ee8680206e46ebe6527165b6d25b06..7ca93516db989f7bb536c73ae800635300b0b59a 100644 (file)
@@ -1,35 +1,35 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:24:1
+  --> $DIR/unsupported.rs:26:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:26:1
+  --> $DIR/unsupported.rs:28:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:28:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"aapcs"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:30:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "aapcs" fn aapcs() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:33:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:38:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index f0debdcf621e29234fb85ea33b64fa54fc60f6b5..9319eac8d30d84bd84be935d7bd7fe0ba49fe17d 100644 (file)
@@ -1,11 +1,13 @@
-// revisions: x64 i686 aarch64
+// revisions: x64 i686 aarch64 arm
 //
 // [x64] needs-llvm-components: x86
-// [x64]compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
+// [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
 // [i686] needs-llvm-components: x86
-// [i686]compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
+// [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
 // [aarch64] needs-llvm-components: aarch64
-// [aarch64]compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
+// [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
+// [arm] needs-llvm-components: arm
+// [arm] compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib
 #![no_core]
 #![feature(
     no_core,
@@ -30,19 +32,25 @@ extern "wasm" fn wasm() {}
 extern "aapcs" fn aapcs() {}
 //[x64]~^ ERROR is not a supported ABI
 //[i686]~^^ ERROR is not a supported ABI
+//[aarch64]~^^^ ERROR is not a supported ABI
 extern "msp430-interrupt" fn msp430() {}
 //~^ ERROR is not a supported ABI
 extern "avr-interrupt" fn avr() {}
 //~^ ERROR is not a supported ABI
 extern "x86-interrupt" fn x86() {}
 //[aarch64]~^ ERROR is not a supported ABI
+//[arm]~^^ ERROR is not a supported ABI
 extern "stdcall" fn stdcall() {}
 //[x64]~^ WARN use of calling convention not supported
 //[x64]~^^ WARN this was previously accepted
 //[aarch64]~^^^ WARN use of calling convention not supported
 //[aarch64]~^^^^ WARN this was previously accepted
+//[arm]~^^^^^ WARN use of calling convention not supported
+//[arm]~^^^^^^ WARN this was previously accepted
 extern "thiscall" fn thiscall() {}
 //[x64]~^ WARN use of calling convention not supported
 //[x64]~^^ WARN this was previously accepted
 //[aarch64]~^^^ WARN use of calling convention not supported
 //[aarch64]~^^^^ WARN this was previously accepted
+//[arm]~^^^^^ WARN use of calling convention not supported
+//[arm]~^^^^^^ WARN this was previously accepted
index 5c68461e4fb392e81f1f7f36d4bec9ef8a9b6f95..f2f52683324dba69576e9759aa00e298d88a7c3c 100644 (file)
@@ -1,57 +1,57 @@
 error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:24:1
+  --> $DIR/unsupported.rs:26:1
    |
 LL | extern "ptx-kernel" fn ptx() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:26:1
+  --> $DIR/unsupported.rs:28:1
    |
 LL | extern "amdgpu-kernel" fn amdgpu() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"wasm"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:28:1
+  --> $DIR/unsupported.rs:30:1
    |
 LL | extern "wasm" fn wasm() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"aapcs"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:30:1
+  --> $DIR/unsupported.rs:32:1
    |
 LL | extern "aapcs" fn aapcs() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:33:1
+  --> $DIR/unsupported.rs:36:1
    |
 LL | extern "msp430-interrupt" fn msp430() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
-  --> $DIR/unsupported.rs:35:1
+  --> $DIR/unsupported.rs:38:1
    |
 LL | extern "avr-interrupt" fn avr() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:39:1
+  --> $DIR/unsupported.rs:43:1
    |
 LL | extern "stdcall" fn stdcall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(unsupported_calling_conventions)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
 warning: use of calling convention not supported on this target
-  --> $DIR/unsupported.rs:44:1
+  --> $DIR/unsupported.rs:50:1
    |
 LL | extern "thiscall" fn thiscall() {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #00000 <https://github.com/rust-lang/rust/issues/00000>
+   = note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
index 45b2889f1ca4c76d037ee1ec07609163120831da..d190d7054fee7df4e980f089d93371782491d959 100644 (file)
@@ -1,6 +1,3 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
-
 fn is_123<const N: usize>(x: [u32; N]) -> bool {
     match x {
         [1, 2] => true, //~ ERROR mismatched types
index 0ad05b3adeb88faf45c31ec42b49a4770c0c5ce0..1a14ab40b1f8623f0292a7ba6cba0f0eeb9db27a 100644 (file)
@@ -1,14 +1,5 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/match_arr_unknown_len.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
 error[E0308]: mismatched types
-  --> $DIR/match_arr_unknown_len.rs:6:9
+  --> $DIR/match_arr_unknown_len.rs:3:9
    |
 LL |         [1, 2] => true,
    |         ^^^^^^ expected `2_usize`, found `N`
@@ -16,6 +7,6 @@ LL |         [1, 2] => true,
    = note: expected array `[u32; 2]`
               found array `[u32; N]`
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0308`.
index 803501b40b68e59d88467682b4b4058256935014..9f487bd8061fc5994d3c7cfed36dcaf91f3dcce0 100644 (file)
@@ -1,6 +1,14 @@
 // only-x86_64
 
-#![feature(asm, global_asm)]
+// Tests that the use of named labels in the `asm!` macro are linted against
+// except for in `#[naked]` fns.
+// Using a named label is incorrect as per the RFC because for most cases
+// the compiler cannot ensure that inline asm is emitted exactly once per
+// codegen unit (except for naked fns) and so the label could be duplicated
+// which causes less readable LLVM errors and in the worst cases causes ICEs
+// or segfaults based on system dependent behavior and codegen flags.
+
+#![feature(asm, global_asm, naked_functions)]
 
 #[no_mangle]
 pub static FOO: usize = 42;
@@ -126,5 +134,61 @@ fn main() {
     }
 }
 
+// Trigger on naked fns too, even though they can't be inlined, reusing a
+// label or LTO can cause labels to break
+#[naked]
+pub extern "C" fn foo() -> i32 {
+    unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+// Make sure that non-naked attributes *do* still let the lint happen
+#[no_mangle]
+pub extern "C" fn bar() {
+    unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+    //~^ ERROR avoid using named labels
+}
+
+#[naked]
+pub extern "C" fn aaa() {
+    fn _local() {}
+
+    unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+}
+
+pub fn normal() {
+    fn _local1() {}
+
+    #[naked]
+    pub extern "C" fn bbb() {
+        fn _very_local() {}
+
+        unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) } //~ ERROR avoid using named labels
+    }
+
+    fn _local2() {}
+}
+
+// Make sure that the lint happens within closures
+fn closures() {
+    || unsafe {
+        asm!("closure1: nop"); //~ ERROR avoid using named labels
+    };
+
+    move || unsafe {
+        asm!("closure2: nop"); //~ ERROR avoid using named labels
+    };
+
+    || {
+        #[naked]
+        unsafe extern "C" fn _nested() {
+            asm!("ret;", options(noreturn));
+        }
+
+        unsafe {
+            asm!("closure3: nop"); //~ ERROR avoid using named labels
+        }
+    };
+}
+
 // Don't trigger on global asm
 global_asm!("aaaaaaaa: nop");
index 3c4a4db75e02de0d28f40c2bf33753ccdfa644a6..396f0a1942428800f0e711f817b4332f941da732 100644 (file)
@@ -1,5 +1,5 @@
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:11:15
+  --> $DIR/named-asm-labels.rs:19:15
    |
 LL |         asm!("bar: nop");
    |               ^^^
@@ -9,7 +9,7 @@ LL |         asm!("bar: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:14:15
+  --> $DIR/named-asm-labels.rs:22:15
    |
 LL |         asm!("abcd:");
    |               ^^^^
@@ -18,7 +18,7 @@ LL |         asm!("abcd:");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:17:15
+  --> $DIR/named-asm-labels.rs:25:15
    |
 LL |         asm!("foo: bar1: nop");
    |               ^^^  ^^^^
@@ -27,7 +27,7 @@ LL |         asm!("foo: bar1: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:21:15
+  --> $DIR/named-asm-labels.rs:29:15
    |
 LL |         asm!("foo1: nop", "nop");
    |               ^^^^
@@ -36,7 +36,7 @@ LL |         asm!("foo1: nop", "nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:22:15
+  --> $DIR/named-asm-labels.rs:30:15
    |
 LL |         asm!("foo2: foo3: nop", "nop");
    |               ^^^^  ^^^^
@@ -45,7 +45,7 @@ LL |         asm!("foo2: foo3: nop", "nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:24:22
+  --> $DIR/named-asm-labels.rs:32:22
    |
 LL |         asm!("nop", "foo4: nop");
    |                      ^^^^
@@ -54,7 +54,7 @@ LL |         asm!("nop", "foo4: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:25:15
+  --> $DIR/named-asm-labels.rs:33:15
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |               ^^^^
@@ -63,7 +63,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:25:28
+  --> $DIR/named-asm-labels.rs:33:28
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |                            ^^^^
@@ -72,7 +72,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:30:15
+  --> $DIR/named-asm-labels.rs:38:15
    |
 LL |         asm!("foo7: nop; foo8: nop");
    |               ^^^^       ^^^^
@@ -81,7 +81,7 @@ LL |         asm!("foo7: nop; foo8: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:32:15
+  --> $DIR/named-asm-labels.rs:40:15
    |
 LL |         asm!("foo9: nop; nop");
    |               ^^^^
@@ -90,7 +90,7 @@ LL |         asm!("foo9: nop; nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:33:20
+  --> $DIR/named-asm-labels.rs:41:20
    |
 LL |         asm!("nop; foo10: nop");
    |                    ^^^^^
@@ -99,7 +99,7 @@ LL |         asm!("nop; foo10: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:36:15
+  --> $DIR/named-asm-labels.rs:44:15
    |
 LL |         asm!("bar2: nop\n bar3: nop");
    |               ^^^^        ^^^^
@@ -108,7 +108,7 @@ LL |         asm!("bar2: nop\n bar3: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:38:15
+  --> $DIR/named-asm-labels.rs:46:15
    |
 LL |         asm!("bar4: nop\n nop");
    |               ^^^^
@@ -117,7 +117,7 @@ LL |         asm!("bar4: nop\n nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:39:21
+  --> $DIR/named-asm-labels.rs:47:21
    |
 LL |         asm!("nop\n bar5: nop");
    |                     ^^^^
@@ -126,7 +126,7 @@ LL |         asm!("nop\n bar5: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:40:21
+  --> $DIR/named-asm-labels.rs:48:21
    |
 LL |         asm!("nop\n bar6: bar7: nop");
    |                     ^^^^  ^^^^
@@ -135,7 +135,7 @@ LL |         asm!("nop\n bar6: bar7: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:46:13
+  --> $DIR/named-asm-labels.rs:54:13
    |
 LL |             blah2: nop
    |             ^^^^^
@@ -146,7 +146,7 @@ LL |             blah3: nop
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:55:19
+  --> $DIR/named-asm-labels.rs:63:19
    |
 LL |             nop ; blah4: nop
    |                   ^^^^^
@@ -155,7 +155,7 @@ LL |             nop ; blah4: nop
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:69:15
+  --> $DIR/named-asm-labels.rs:77:15
    |
 LL |         asm!("blah1: 2bar: nop");
    |               ^^^^^
@@ -164,7 +164,7 @@ LL |         asm!("blah1: 2bar: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:72:15
+  --> $DIR/named-asm-labels.rs:80:15
    |
 LL |         asm!("def: def: nop");
    |               ^^^
@@ -173,7 +173,7 @@ LL |         asm!("def: def: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:73:15
+  --> $DIR/named-asm-labels.rs:81:15
    |
 LL |         asm!("def: nop\ndef: nop");
    |               ^^^
@@ -182,7 +182,7 @@ LL |         asm!("def: nop\ndef: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:74:15
+  --> $DIR/named-asm-labels.rs:82:15
    |
 LL |         asm!("def: nop; def: nop");
    |               ^^^
@@ -191,7 +191,7 @@ LL |         asm!("def: nop; def: nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:82:15
+  --> $DIR/named-asm-labels.rs:90:15
    |
 LL |         asm!("fooo\u{003A} nop");
    |               ^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |         asm!("fooo\u{003A} nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:83:15
+  --> $DIR/named-asm-labels.rs:91:15
    |
 LL |         asm!("foooo\x3A nop");
    |               ^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |         asm!("foooo\x3A nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:86:15
+  --> $DIR/named-asm-labels.rs:94:15
    |
 LL |         asm!("fooooo:\u{000A} nop");
    |               ^^^^^^
@@ -218,7 +218,7 @@ LL |         asm!("fooooo:\u{000A} nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:87:15
+  --> $DIR/named-asm-labels.rs:95:15
    |
 LL |         asm!("foooooo:\x0A nop");
    |               ^^^^^^^
@@ -227,7 +227,7 @@ LL |         asm!("foooooo:\x0A nop");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:91:14
+  --> $DIR/named-asm-labels.rs:99:14
    |
 LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:102:13
+  --> $DIR/named-asm-labels.rs:110:13
    |
 LL |             ab: nop // ab: does foo
    |             ^^
@@ -245,7 +245,7 @@ LL |             ab: nop // ab: does foo
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:114:14
+  --> $DIR/named-asm-labels.rs:122:14
    |
 LL |         asm!(include_str!("named-asm-labels.s"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -254,18 +254,81 @@ LL |         asm!(include_str!("named-asm-labels.s"));
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
 warning: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:124:19
+  --> $DIR/named-asm-labels.rs:132:19
    |
 LL |             asm!("warned: nop");
    |                   ^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/named-asm-labels.rs:122:16
+  --> $DIR/named-asm-labels.rs:130:16
    |
 LL |         #[warn(named_asm_labels)]
    |                ^^^^^^^^^^^^^^^^
    = help: only local labels of the form `<number>:` should be used in inline asm
    = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
 
-error: aborting due to 28 previous errors; 1 warning emitted
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:141:20
+   |
+LL |     unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:147:20
+   |
+LL |     unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:155:20
+   |
+LL |     unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
+   |                    ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:165:24
+   |
+LL |         unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
+   |                        ^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:174:15
+   |
+LL |         asm!("closure1: nop");
+   |               ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:178:15
+   |
+LL |         asm!("closure2: nop");
+   |               ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: avoid using named labels in inline assembly
+  --> $DIR/named-asm-labels.rs:188:19
+   |
+LL |             asm!("closure3: nop");
+   |                   ^^^^^^^^
+   |
+   = help: only local labels of the form `<number>:` should be used in inline asm
+   = note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
+
+error: aborting due to 35 previous errors; 1 warning emitted
 
index ad981d93d514e8e3d1d1985a837055fe4e403593..5edbcf4a2a7c939a327dc66b1a9e8042d31de97a 100644 (file)
@@ -25,6 +25,21 @@ LL |         let x = 0;
 LL |         asm!("{}", const const_bar(x));
    |                                    ^ non-constant value
 
+error[E0308]: mismatched types
+  --> $DIR/type-check-1.rs:48:26
+   |
+LL |         asm!("{}", const 0f32);
+   |                          ^^^^ expected integer, found `f32`
+
+error[E0308]: mismatched types
+  --> $DIR/type-check-1.rs:50:26
+   |
+LL |         asm!("{}", const 0 as *mut u8);
+   |                          ^^^^^^^^^^^^ expected integer, found *-ptr
+   |
+   = note:     expected type `{integer}`
+           found raw pointer `*mut u8`
+
 error: invalid asm output
   --> $DIR/type-check-1.rs:10:29
    |
@@ -64,21 +79,6 @@ LL |         asm!("{}", inout(reg) v[..]);
    = help: the trait `Sized` is not implemented for `[u64]`
    = note: all inline asm arguments must have a statically known size
 
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:48:26
-   |
-LL |         asm!("{}", const 0f32);
-   |                          ^^^^ expected integer, found `f32`
-
-error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:50:26
-   |
-LL |         asm!("{}", const 0 as *mut u8);
-   |                          ^^^^^^^^^^^^ expected integer, found *-ptr
-   |
-   = note:     expected type `{integer}`
-           found raw pointer `*mut u8`
-
 error[E0308]: mismatched types
   --> $DIR/type-check-1.rs:60:25
    |
index d3a1cd30e2be60512ea5dd8a78efa8bfa8573216..46a54a12d624519aa1fab7e9d2594bab846d1d31 100644 (file)
@@ -5,7 +5,7 @@ LL |     let _array: [u32; <A as Foo>::Y];
    |                        ^ cannot perform const operation using `A`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 0d84dca5b8099dd28252c8fc0444d06a614a32f0..f2e4ca524a4391bbb5221dfb51018baa9b273f6b 100644 (file)
@@ -5,7 +5,7 @@ LL |     links: [u32; A::LINKS], // Shouldn't suggest bounds already there.
    |                  ^^^^^^^^ cannot perform const operation using `A`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index e72ef0e4b332ea2cea0e4d881ea93dab4f95f0f8..4162cdaa8dcd87995264d4e461f3009622f9f2cb 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing the super traits of `Baz` with assoc
 LL | trait Baz: Foo + Bar<Self::Item> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires computing the super traits of `Baz` with associated type name `Item`, completing the cycle
+   = note: ...which immediately requires computing the super traits of `Baz` with associated type name `Item` again
 note: cycle used when computing the super traits of `Baz`
   --> $DIR/ambiguous-associated-type2.rs:7:1
    |
index a694f88192ed62878fce5198f248d9cc4f29b2b0..57aacf67e05fd8919da971f76449af18101c69f4 100644 (file)
@@ -8,8 +8,10 @@ LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
 note: required by a bound in `Send`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
    |
-LL | pub unsafe auto trait Send {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Send`
+LL | / pub unsafe auto trait Send {
+LL | |     // empty.
+LL | | }
+   | |_^ required by this bound in `Send`
 help: consider further restricting the associated type
    |
 LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send {
@@ -25,8 +27,14 @@ LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
 note: required by a bound in `Iterator`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    |
-LL | pub trait Iterator {
-   | ^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator`
+LL | / pub trait Iterator {
+LL | |     /// The type of the elements being iterated over.
+LL | |     #[stable(feature = "rust1", since = "1.0.0")]
+LL | |     type Item;
+...  |
+LL | |     }
+LL | | }
+   | |_^ required by this bound in `Iterator`
 help: consider further restricting the associated type
    |
 LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator {
@@ -42,8 +50,14 @@ LL |     type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8
 note: required by a bound in `Sync`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
    |
-LL | pub unsafe auto trait Sync {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Sync`
+LL | / pub unsafe auto trait Sync {
+LL | |     // FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
+LL | |     // lands in beta, and it has been extended to check whether a closure is
+LL | |     // anywhere in the requirement chain, extend it as such (#48534):
+...  |
+LL | |     // Empty
+LL | | }
+   | |_^ required by this bound in `Sync`
 help: consider further restricting the associated type
    |
 LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync {
index 775fe28f00d83910e5b0b2a2a914c3c9ab84d72e..4da5a2cbd41a6b588bc35a07ef146de7a68b874a 100644 (file)
@@ -8,8 +8,14 @@ LL |     type A: Iterator<Item: Debug>;
 note: required by a bound in `Debug`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
-LL | pub trait Debug {
-   | ^^^^^^^^^^^^^^^ required by this bound in `Debug`
+LL | / pub trait Debug {
+LL | |     /// Formats the value using the given formatter.
+LL | |     ///
+LL | |     /// # Examples
+...  |
+LL | |     fn fmt(&self, f: &mut Formatter<'_>) -> Result;
+LL | | }
+   | |_^ required by this bound in `Debug`
 help: consider further restricting the associated type
    |
 LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug {
@@ -24,8 +30,14 @@ LL | pub trait Foo { type Out: Baz<Assoc: Default>; }
 note: required by a bound in `Default`
   --> $SRC_DIR/core/src/default.rs:LL:COL
    |
-LL | pub trait Default: Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Default`
+LL | / pub trait Default: Sized {
+LL | |     /// Returns the "default value" for a type.
+LL | |     ///
+LL | |     /// Default values are often some kind of initial value, identity value, or anything else that
+...  |
+LL | |     fn default() -> Self;
+LL | | }
+   | |_^ required by this bound in `Default`
 help: consider further restricting the associated type
    |
 LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; }
index 8f0a9ea3566fb0a423784e16811e0deb4d73a05d..a02208661f1f7b5449b23aa7fd0107882a7fbfef 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 #![feature(associated_type_bounds)]
 
 trait TraitA<'a> {
@@ -34,6 +36,4 @@ fn foo<T>()
 
 fn main() {
     foo::<Z>();
-    //~^ ERROR: the trait bound `for<'a, 'b> <Z as TraitA<'a>>::AsA: TraitB<'a, 'b>` is not satisfied
-    //~| ERROR: the trait bound `for<'a, 'b, 'c> <<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied
 }
diff --git a/src/test/ui/associated-type-bounds/issue-83017.stderr b/src/test/ui/associated-type-bounds/issue-83017.stderr
deleted file mode 100644 (file)
index af86990..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0277]: the trait bound `for<'a, 'b> <Z as TraitA<'a>>::AsA: TraitB<'a, 'b>` is not satisfied
-  --> $DIR/issue-83017.rs:36:5
-   |
-LL |     foo::<Z>();
-   |     ^^^^^^^^ the trait `for<'a, 'b> TraitB<'a, 'b>` is not implemented for `<Z as TraitA<'a>>::AsA`
-   |
-note: required by a bound in `foo`
-  --> $DIR/issue-83017.rs:31:32
-   |
-LL | fn foo<T>()
-   |    --- required by a bound in this
-LL | where
-LL |     for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>,
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0277]: the trait bound `for<'a, 'b, 'c> <<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB: TraitC<'a, 'b, 'c>` is not satisfied
-  --> $DIR/issue-83017.rs:36:5
-   |
-LL |     foo::<Z>();
-   |     ^^^^^^^^ the trait `for<'a, 'b, 'c> TraitC<'a, 'b, 'c>` is not implemented for `<<Z as TraitA<'a>>::AsA as TraitB<'a, 'b>>::AsB`
-   |
-note: required by a bound in `foo`
-  --> $DIR/issue-83017.rs:31:60
-   |
-LL | fn foo<T>()
-   |    --- required by a bound in this
-LL | where
-LL |     for<'a> T: TraitA<'a, AsA: for<'b> TraitB<'a, 'b, AsB: for<'c> TraitC<'a, 'b, 'c>>>,
-   |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 59e27cd2e7dd6e2b8bc014d8bb37bc4acb0e9d4e..e3bd0c2276e48ca2ac120a84844aa81ff52c1d5d 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     foo(());
    |     ^^^^^^^ one type is more general than the other
    |
-   = note:   expected type `&'a ()`
-           found reference `&()`
+   = note: expected reference `&'a ()`
+              found reference `&()`
 
 error: aborting due to previous error
 
index e2847b6b72b8638f741e7a8d9ff8f71ee9d2f682..1ac72e4b90c75d0f4455b760b83e14e30608158e 100644 (file)
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     foo(());
    |     ^^^ lifetime mismatch
    |
-   = note: expected type `&'a ()`
-              found type `&()`
+   = note: expected reference `&'a ()`
+                   found type `&()`
 note: the lifetime requirement is introduced here
   --> $DIR/higher-ranked-projection.rs:15:33
    |
index cdf32dd82a6a909181bc8a1bd09f0a34ae172c6a..db414164e1663900866c7c2ad77a7596dd25b65a 100644 (file)
@@ -10,7 +10,7 @@ fn f(&self, x: &Self::U) {
 
 impl X<'_> for i32 {
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <i32 as X<'b>>::U: Clone`
+    //~^ ERROR the trait bound `str: Clone`
 }
 
 fn main() {
index 0bcc9be5c43ceec0b55c816b7217992a99ed2c4e..4eed5c9a0083c18f6098d51d362a294066d44709 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <i32 as X<'b>>::U: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-1.rs:12:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<i32 as X<'b>>::U`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `X`
   --> $DIR/hr-associated-type-bound-1.rs:3:33
    |
index 78ee28b17d4b393cbbfd6c5a53c47a38537e2a29..2eb956c8dbb08f61a29433f4e6383545b883db64 100644 (file)
@@ -8,14 +8,13 @@ fn f(&self, x: &Self::U) {
     }
 }
 
-impl X<'_> for u32
+impl X<'_> for u32 //~ overflow evaluating the requirement `for<'b> u32: X<'b>`
 where
     for<'b> <Self as X<'b>>::U: Clone,
 {
-    type U = str;
+    type U = str; //~ overflow evaluating the requirement `for<'b> u32: X<'b>`
 }
 
 fn main() {
     1u32.f("abc");
-    //~^ ERROR the method
 }
index 043d1ac76de9a6c7bd0b9cac0e0a24714a69edda..079989f2331af77815e92c5e36c3166b495b505a 100644 (file)
@@ -1,13 +1,38 @@
-error[E0599]: the method `f` exists for type `u32`, but its trait bounds were not satisfied
-  --> $DIR/hr-associated-type-bound-2.rs:19:10
+error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>`
+  --> $DIR/hr-associated-type-bound-2.rs:11:1
    |
-LL |     1u32.f("abc");
-   |          ^ method cannot be called on `u32` due to unsatisfied trait bounds
+LL | / impl X<'_> for u32
+LL | | where
+LL | |     for<'b> <Self as X<'b>>::U: Clone,
+LL | | {
+LL | |     type U = str;
+LL | | }
+   | |_^
    |
-   = note: the following trait bounds were not satisfied:
-           `<u32 as X<'b>>::U: Clone`
-           which is required by `u32: X`
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`)
+note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
+  --> $DIR/hr-associated-type-bound-2.rs:11:6
+   |
+LL | impl X<'_> for u32
+   |      ^^^^^     ^^^
+   = note: 128 redundant requirements hidden
+   = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
+
+error[E0275]: overflow evaluating the requirement `for<'b> u32: X<'b>`
+  --> $DIR/hr-associated-type-bound-2.rs:15:5
+   |
+LL |     type U = str;
+   |     ^^^^^^^^^^^^^
+   |
+   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`hr_associated_type_bound_2`)
+note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
+  --> $DIR/hr-associated-type-bound-2.rs:11:6
+   |
+LL | impl X<'_> for u32
+   |      ^^^^^     ^^^
+   = note: 128 redundant requirements hidden
+   = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0599`.
+For more information about this error, try `rustc --explain E0275`.
index 0a81f373ad4c5a654db3e7177df546ac7e5fcb10..bbeeb145d1fe298197e39bdd28742216ebbe9198 100644 (file)
@@ -12,7 +12,7 @@ fn g(&self, x: &Self::V) {
 
 impl<'a> Y<'a, u8> for u8 {
     type V = str;
-    //~^ ERROR the trait bound `for<'b> <u8 as Y<'b, u8>>::V: Clone` is not satisfied
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
 }
 
 fn main() {
index e16931ee09fc67647829da48854b640845b4c624..99f95c200511ac4c017f5e7ef904ae53309f4d1d 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <u8 as Y<'b, u8>>::V: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-1.rs:14:14
    |
 LL |     type V = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<u8 as Y<'b, u8>>::V`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `Y`
   --> $DIR/hr-associated-type-bound-param-1.rs:4:36
    |
index a04144ba06b6577be3ce5b4be34c198abac95f63..5193400882d1255f83eea4be2e4ca33229c4456e 100644 (file)
@@ -2,8 +2,8 @@
 trait Z<'a, T: ?Sized>
 where
     T: Z<'a, u16>,
-    //~^ the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
-    //~| the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
+    //~^ the trait bound `str: Clone` is not satisfied
+    //~| the trait bound `str: Clone` is not satisfied
     for<'b> <T as Z<'b, u16>>::W: Clone,
 {
     type W: ?Sized;
@@ -14,7 +14,7 @@ fn h(&self, x: &T::W) {
 
 impl<'a> Z<'a, u16> for u16 {
     type W = str;
-    //~^ ERROR the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone
+    //~^ ERROR the trait bound `str: Clone
 }
 
 fn main() {
index 0c9f2a3978cd15247a0170577b504ea0d241e0af..730229b5208da70e32b7687be78a0c11639f5d5e 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-2.rs:4:8
    |
 LL |     T: Z<'a, u16>,
-   |        ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
+   |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `Z`
   --> $DIR/hr-associated-type-bound-param-2.rs:7:35
    |
@@ -15,14 +13,12 @@ LL | trait Z<'a, T: ?Sized>
 LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
-error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-2.rs:4:8
    |
 LL |     T: Z<'a, u16>,
-   |        ^^^^^^^^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
+   |        ^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `Z`
   --> $DIR/hr-associated-type-bound-param-2.rs:7:35
    |
@@ -32,14 +28,12 @@ LL | trait Z<'a, T: ?Sized>
 LL |     for<'b> <T as Z<'b, u16>>::W: Clone,
    |                                   ^^^^^ required by this bound in `Z`
 
-error[E0277]: the trait bound `for<'b> <u16 as Z<'b, u16>>::W: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-2.rs:16:14
    |
 LL |     type W = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<u16 as Z<'b, u16>>::W`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `Z`
   --> $DIR/hr-associated-type-bound-param-2.rs:7:35
    |
index 1af63bf9070a1c2ed906e1f96382e9b8281a1d4f..fda7d8111856da4cfc6ec2a1e3b4c26cd5482dbc 100644 (file)
@@ -11,7 +11,7 @@ fn f(x: &<T as X<'_, T>>::U) {
 
 impl<S, T> X<'_, (T,)> for (S,) {
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` is not satisfied
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
 }
 
 pub fn main() {
index b1bc1dfbb112729fb1c23141d16fc1dd7a654d72..9935445c306586c88a33a6ae53f6ac923839f0c4 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <(T,) as X<'b, (T,)>>::U: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-3.rs:13:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<(T,) as X<'b, (T,)>>::U`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `X`
   --> $DIR/hr-associated-type-bound-param-3.rs:4:33
    |
index 6f06b925bd2e808998ec8b5d326b1e1ba20d9625..20c8157ed974921e6ff79567f92db9b10cc9a026 100644 (file)
@@ -11,7 +11,7 @@ fn f(x: &<(T,) as X<'_, T>>::U) {
 
 impl<S, T> X<'_, T> for (S,) {
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <(T,) as X<'b, T>>::U: Clone` is not satisfied
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
 }
 
 pub fn main() {
index 0bd404f8a41b29b5358d6d244f55061dd18a76ae..c26324ee6255455da3fe2d642c09ab79e26f5492 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <(T,) as X<'b, T>>::U: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-4.rs:13:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<(T,) as X<'b, T>>::U`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `X`
   --> $DIR/hr-associated-type-bound-param-4.rs:4:36
    |
index fc3a85171e273eedcad878c6c8111cbd28641fd7..920aa835280701e159dfc2866ed41ecf11ae2c76 100644 (file)
@@ -25,14 +25,12 @@ fn f(x: &<T as X<'_, T>>::U) {
 
 impl<S, T> X<'_, Vec<T>> for S {
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <Box<T> as X<'b, Box<T>>>::U: Clone` is not satisfied
-    //~| ERROR the trait bound `for<'b> <Vec<T> as X<'b, Vec<T>>>::U: Clone` is not satisfied
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
 }
 
 impl<S, T> X<'_, Box<T>> for S {
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <Box<T> as X<'b, Box<T>>>::U: Clone` is not satisfied
-    //~| ERROR the trait bound `for<'b> <Vec<T> as X<'b, Vec<T>>>::U: Clone` is not satisfied
+    //~^ ERROR the trait bound `str: Clone` is not satisfied
 }
 
 pub fn main() {
index 59c0a7268cc833be32f1b70f3914708158a748ad..63cd89316b38cf6a94bbfbd19106ba8d2cbbeb0c 100644 (file)
@@ -1,11 +1,9 @@
-error[E0277]: the trait bound `for<'b> <Box<T> as X<'b, Box<T>>>::U: Clone` is not satisfied
+error[E0277]: the trait bound `str: Clone` is not satisfied
   --> $DIR/hr-associated-type-bound-param-5.rs:27:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<Box<T> as X<'b, Box<T>>>::U`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `X`
   --> $DIR/hr-associated-type-bound-param-5.rs:18:45
    |
@@ -15,31 +13,12 @@ LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
 LL |     for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
    |                                             ^^^^^ required by this bound in `X`
 
-error[E0277]: the trait bound `for<'b> <Vec<T> as X<'b, Vec<T>>>::U: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-5.rs:27:14
-   |
-LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<Vec<T> as X<'b, Vec<T>>>::U`
-   |
-   = help: the following implementations were found:
-             <&T as Clone>
-note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-5.rs:16:33
-   |
-LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
-   |       - required by a bound in this
-LL | where
-LL |     for<'b> <T as X<'b, T>>::U: Clone,
-   |                                 ^^^^^ required by this bound in `X`
-
-error[E0277]: the trait bound `for<'b> <Vec<T> as X<'b, Vec<T>>>::U: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-5.rs:33:14
+error[E0277]: the trait bound `str: Clone` is not satisfied
+  --> $DIR/hr-associated-type-bound-param-5.rs:32:14
    |
 LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<Vec<T> as X<'b, Vec<T>>>::U`
+   |              ^^^ the trait `Clone` is not implemented for `str`
    |
-   = help: the following implementations were found:
-             <&T as Clone>
 note: required by a bound in `X`
   --> $DIR/hr-associated-type-bound-param-5.rs:18:45
    |
@@ -49,23 +28,6 @@ LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
 LL |     for<'b> <T::Next as X<'b, T::Next>>::U: Clone,
    |                                             ^^^^^ required by this bound in `X`
 
-error[E0277]: the trait bound `for<'b> <Box<T> as X<'b, Box<T>>>::U: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-5.rs:33:14
-   |
-LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<Box<T> as X<'b, Box<T>>>::U`
-   |
-   = help: the following implementations were found:
-             <&T as Clone>
-note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-5.rs:16:33
-   |
-LL | trait X<'a, T: Cycle + for<'b> X<'b, T>>
-   |       - required by a bound in this
-LL | where
-LL |     for<'b> <T as X<'b, T>>::U: Clone,
-   |                                 ^^^^^ required by this bound in `X`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index 04b88c7f4fcb4bf9e0042b2f11f6ad86f55cf460..482047b095925a45d6dce447c56dc20615c56fb6 100644 (file)
@@ -12,7 +12,6 @@ fn f(x: &<T as X<'_, T>>::U) {
 impl<S, T> X<'_, T> for (S,) {
     //~^ ERROR the trait bound `for<'b> T: X<'b, T>` is not satisfied
     type U = str;
-    //~^ ERROR the trait bound `for<'b> <T as X<'b, T>>::U: Clone` is not satisfied
 }
 
 pub fn main() {
index bce5737af1bb626ab1b018fe091334a5e10b608a..bd6e627a3d0d577f43fbc1f76769991681a52ff5 100644 (file)
@@ -1,39 +1,14 @@
-error[E0277]: the trait bound `for<'b> <T as X<'b, T>>::U: Clone` is not satisfied
-  --> $DIR/hr-associated-type-bound-param-6.rs:14:14
-   |
-LL |     type U = str;
-   |              ^^^ the trait `for<'b> Clone` is not implemented for `<T as X<'b, T>>::U`
-   |
-   = help: the following implementations were found:
-             <&T as Clone>
-note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-6.rs:4:33
-   |
-LL | trait X<'a, T>
-   |       - required by a bound in this
-...
-LL |     for<'b> <T as X<'b, T>>::U: Clone,
-   |                                 ^^^^^ required by this bound in `X`
-
 error[E0277]: the trait bound `for<'b> T: X<'b, T>` is not satisfied
   --> $DIR/hr-associated-type-bound-param-6.rs:12:12
    |
 LL | impl<S, T> X<'_, T> for (S,) {
    |            ^^^^^^^^ the trait `for<'b> X<'b, T>` is not implemented for `T`
    |
-note: required by a bound in `X`
-  --> $DIR/hr-associated-type-bound-param-6.rs:3:16
-   |
-LL | trait X<'a, T>
-   |       - required by a bound in this
-LL | where
-LL |     for<'b> T: X<'b, T>,
-   |                ^^^^^^^^ required by this bound in `X`
 help: consider restricting type parameter `T`
    |
 LL | impl<S, T: for<'b> X<'b, T>> X<'_, T> for (S,) {
    |          ++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index bad736b64c038122dc7988cae58fb89600e997c7..951dd9e97d268ec81274dc44f21fb895b57d35dd 100644 (file)
@@ -11,9 +11,8 @@ fn bug(item: &Self::Item) -> () {
 }
 
 impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-    //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+    //~^ type mismatch resolving `<T as Deref>::Target == T`
     type Item = T;
-    //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref
 }
 
 pub fn main() {
index 20d7a206754ea64b8530ce262ea0f458e4f84e21..9c29e969de8da77a123c453d33b244a80f306090 100644 (file)
@@ -1,32 +1,16 @@
-error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
-  --> $DIR/hr-associated-type-projection-1.rs:15:17
-   |
-LL |     type Item = T;
-   |                 ^ the trait `for<'b> Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
-   |
-   = help: the following implementations were found:
-             <&T as Deref>
-             <&mut T as Deref>
-note: required by a bound in `UnsafeCopy`
-  --> $DIR/hr-associated-type-projection-1.rs:3:48
-   |
-LL | trait UnsafeCopy<'a, T: Copy>
-   |       ---------- required by a bound in this
-LL | where
-LL |     for<'b> <Self as UnsafeCopy<'b, T>>::Item: std::ops::Deref<Target = T>,
-   |                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UnsafeCopy`
-
-error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
+error[E0271]: type mismatch resolving `<T as Deref>::Target == T`
   --> $DIR/hr-associated-type-projection-1.rs:13:33
    |
 LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
-   |                                 ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
+   |      - this type parameter      ^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `T`
    |
-help: consider further restricting the associated type
+   = note: expected associated type `<T as Deref>::Target`
+               found type parameter `T`
+help: consider further restricting this bound
    |
-LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref {
-   |                                                         +++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | impl<T: Copy + std::ops::Deref + Deref<Target = T>> UnsafeCopy<'_, T> for T {
+   |                                +++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/normalization-generality-2.rs b/src/test/ui/associated-types/normalization-generality-2.rs
new file mode 100644 (file)
index 0000000..d8790bb
--- /dev/null
@@ -0,0 +1,30 @@
+// build-pass
+
+// Ensures that we don't regress on "implementation is not general enough" when
+// normalizating under binders. Unlike `normalization-generality.rs`, this also produces
+// type outlives predicates that we must ignore.
+
+pub unsafe trait Yokeable<'a> {
+    type Output: 'a;
+}
+pub struct Yoke<Y: for<'a> Yokeable<'a>> {
+    _marker: std::marker::PhantomData<Y>,
+}
+impl<Y: for<'a> Yokeable<'a>> Yoke<Y> {
+    pub fn project<P>(
+        &self,
+        _f: for<'a> fn(&<Y as Yokeable<'a>>::Output, &'a ()) -> <P as Yokeable<'a>>::Output,
+    ) -> Yoke<P>
+    where
+        P: for<'a> Yokeable<'a>,
+    {
+        unimplemented!()
+    }
+}
+pub fn slice(y: Yoke<&'static str>) -> Yoke<&'static [u8]> {
+    y.project(move |yk, _| yk.as_bytes())
+}
+unsafe impl<'a, T: 'static + ?Sized> Yokeable<'a> for &'static T {
+    type Output = &'a T;
+}
+fn main() {}
index 0307875c154b8bc291f608841b70dd4eba35bb85..8961655ede36f6fc4dad99eeba8bb18096f636ba 100644 (file)
@@ -1 +1 @@
-{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
index 535f57bf6af85776077724557ef3a5408373edf2..082f04134ce8f387eebe81f373327ae5dd12fd8a 100644 (file)
@@ -1 +1 @@
-{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"rust_2015","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"span":{"lo":0,"hi":0}}
index 43364a8e85896071df82add403f150d1c053855c..8fb570d67562ab65bac889ef0cd538b902d90674 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0706]: functions in traits cannot be declared `async`
index 37ebb4ecac8b8db31211c58411b9fd5febe1129b..cc6dc38346907a0362db6fa6695f1e24ffa58d55 100644 (file)
@@ -1,7 +1,7 @@
 // edition:2018
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo;
index 1402f1ca92ba8baa9a5b569b42fd41a6d5bea9e1..f2e0fb19c631d366d6cfeee44abccb81ecc701a8 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 = "2018"` in `Cargo.toml`
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
     //~| 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 = "2018"` in `Cargo.toml`
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
     //~| 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 = "2018"` in `Cargo.toml`
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
     //~| 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 = "2018"` in `Cargo.toml`
+    //~| HELP set `edition = "2021"` in `Cargo.toml`
     //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
 }
index 9ac2bc5cc89648f34f1d58d2b0a5694baf8640a5..b38c897fc7447aa8ff1866596907ec87d7e48b54 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 = "2018"` in `Cargo.toml`
+   = 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`
@@ -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 = "2018"` in `Cargo.toml`
+   = 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 = ()>>`
@@ -25,7 +25,7 @@ LL |     x.await;
    |       ^^^^^ unknown field
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2018"` in `Cargo.toml`
+   = 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 = ()>`
@@ -35,7 +35,7 @@ LL |     x.await;
    |       ^^^^^
    |
    = note: to `.await` a `Future`, switch to Rust 2018 or later
-   = help: set `edition = "2018"` in `Cargo.toml`
+   = 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
diff --git a/src/test/ui/binding/const-param.full.stderr b/src/test/ui/binding/const-param.full.stderr
deleted file mode 100644 (file)
index 0200c6d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0158]: const parameters cannot be referenced in patterns
-  --> $DIR/const-param.rs:8:9
-   |
-LL |         N => {}
-   |         ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0158`.
diff --git a/src/test/ui/binding/const-param.min.stderr b/src/test/ui/binding/const-param.min.stderr
deleted file mode 100644 (file)
index 0200c6d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0158]: const parameters cannot be referenced in patterns
-  --> $DIR/const-param.rs:8:9
-   |
-LL |         N => {}
-   |         ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0158`.
index 4aec801cb1552df3eec4b18eae7ba7954bca843d..2d051808fe0bea703105a9fb015ce93545992304 100644 (file)
@@ -1,7 +1,4 @@
 // Identifier pattern referring to a const generic parameter is an error (issue #68853).
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 fn check<const N: usize>() {
     match 1 {
diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr
new file mode 100644 (file)
index 0000000..adda808
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0158]: const parameters cannot be referenced in patterns
+  --> $DIR/const-param.rs:5:9
+   |
+LL |         N => {}
+   |         ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0158`.
index cecc278e1931cb8684a5c1a200af7cd127689c71..6e63de9136cb19a2f5c0aa23c983e33ffd39769b 100644 (file)
@@ -14,8 +14,8 @@ fn distinct_variant() {
     // also used for the discriminant of `Foo`, which it would be if `a` was a
     // reference.
     let b = match y {
-      Foo::Y(_, ref mut b) => b,
       //~^ ERROR cannot use `y`
+      Foo::Y(_, ref mut b) => b,
       Foo::X => panic!()
     };
 
@@ -32,8 +32,9 @@ fn same_variant() {
     };
 
     let b = match y {
-      Foo::Y(ref mut b, _) => b, //~ ERROR cannot use `y`
-      //~| ERROR cannot borrow `y.0` as mutable
+      //~^ ERROR cannot use `y`
+      Foo::Y(ref mut b, _) => b,
+      //~^ ERROR cannot borrow `y.0` as mutable
       Foo::X => panic!()
     };
 
index 2caeed1bd44ea634edd497d34858378ca97fb988..98f6f00a7d48bbdb6a725d0af80d535854020fea 100644 (file)
@@ -1,29 +1,29 @@
 error[E0503]: cannot use `y` because it was mutably borrowed
-  --> $DIR/borrowck-anon-fields-variant.rs:17:7
+  --> $DIR/borrowck-anon-fields-variant.rs:16:19
    |
 LL |       Foo::Y(ref mut a, _) => a,
    |              --------- borrow of `y.0` occurs here
 ...
-LL |       Foo::Y(_, ref mut b) => b,
-   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+LL |     let b = match y {
+   |                   ^ use of borrowed `y.0`
 ...
 LL |     *a += 1;
    |     ------- borrow later used here
 
 error[E0503]: cannot use `y` because it was mutably borrowed
-  --> $DIR/borrowck-anon-fields-variant.rs:35:7
+  --> $DIR/borrowck-anon-fields-variant.rs:34:19
    |
 LL |       Foo::Y(ref mut a, _) => a,
    |              --------- borrow of `y.0` occurs here
 ...
-LL |       Foo::Y(ref mut b, _) => b,
-   |       ^^^^^^^^^^^^^^^^^^^^ use of borrowed `y.0`
+LL |     let b = match y {
+   |                   ^ use of borrowed `y.0`
 ...
 LL |     *a += 1;
    |     ------- borrow later used here
 
 error[E0499]: cannot borrow `y.0` as mutable more than once at a time
-  --> $DIR/borrowck-anon-fields-variant.rs:35:14
+  --> $DIR/borrowck-anon-fields-variant.rs:36:14
    |
 LL |       Foo::Y(ref mut a, _) => a,
    |              --------- first mutable borrow occurs here
index 0e6c0635adb45dce953311af9de061e78610555b..cdcff69d6e529293998ce23f69128630dd1aafec 100644 (file)
@@ -164,9 +164,9 @@ enum E<X> { A(X), B { x: X } }
         let mut e = E::A(3);
         let x = &mut e;
         match e {
+            //~^ ERROR cannot use `e` because it was mutably borrowed
             E::A(ref ax) =>
                 //~^ ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable
-                //~| ERROR cannot use `e` because it was mutably borrowed
                 println!("e.ax: {:?}", ax),
             E::B { x: ref bx } =>
                 //~^ ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable
index 0f2ebbcbf3cdb6a06c53d614ca860a94acb448e0..4b9c5a2a98ff67861b63422e1116d0dfd996a081 100644 (file)
@@ -238,23 +238,22 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:167:13
+  --> $DIR/borrowck-describe-lvalue.rs:166:15
    |
 LL |         let x = &mut e;
    |                 ------ borrow of `e` occurs here
 LL |         match e {
-LL |             E::A(ref ax) =>
-   |             ^^^^^^^^^^^^ use of borrowed `e`
+   |               ^ use of borrowed `e`
 ...
 LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:167:18
+  --> $DIR/borrowck-describe-lvalue.rs:168:18
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
-LL |         match e {
+...
 LL |             E::A(ref ax) =>
    |                  ^^^^^^ immutable borrow occurs here
 ...
index c766e6c108086dd8b11b09aeeb3828b4431df105..a925cbbf57b6d6ef0e90c11c19721ec127a15e46 100644 (file)
@@ -6,8 +6,8 @@ enum Foo {
 fn match_enum() {
     let mut foo = Foo::B;
     let p = &mut foo;
-    let _ = match foo {
-        Foo::B => 1, //~ ERROR [E0503]
+    let _ = match foo { //~ ERROR [E0503]
+        Foo::B => 1,
         _ => 2,
         Foo::A(x) => x //~ ERROR [E0503]
     };
index 286a925bb7f6ccd72a072b3102b69c1714f7d2fa..39047be9de670e667bcd9517168ee5ad6140d64e 100644 (file)
@@ -1,11 +1,10 @@
 error[E0503]: cannot use `foo` because it was mutably borrowed
-  --> $DIR/borrowck-match-already-borrowed.rs:10:9
+  --> $DIR/borrowck-match-already-borrowed.rs:9:19
    |
 LL |     let p = &mut foo;
    |             -------- borrow of `foo` occurs here
 LL |     let _ = match foo {
-LL |         Foo::B => 1,
-   |         ^^^^^^ use of borrowed `foo`
+   |                   ^^^ use of borrowed `foo`
 ...
 LL |     drop(p);
    |          - borrow later used here
index 71f1f15654b55355ce23a912a5de0d30f1a8f3ba..4109c10e2e46bf6bb9a17a05ca048b65f4b1c641 100644 (file)
 fn main() {
     let b = &mut true;
     match b {
+        //~^ ERROR use of moved value: `b` [E0382]
         &mut false => {},
         _ if { (|| { let bar = b; *bar = false; })();
                      false } => { },
         &mut true => { println!("You might think we should get here"); },
-        //~^ ERROR use of moved value: `b` [E0382]
         _ => panic!("surely we could never get here, since rustc warns it is unreachable."),
     }
 }
index 51f9b464d7660e842f1c613f9fce141efedac0aa..9be1a9279992b813037fe28e38d492df4694d09f 100644 (file)
@@ -1,16 +1,15 @@
 error[E0382]: use of moved value: `b`
-  --> $DIR/issue-27282-move-match-input-into-guard.rs:16:14
+  --> $DIR/issue-27282-move-match-input-into-guard.rs:12:5
    |
 LL |     let b = &mut true;
    |         - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait
+LL |     match b {
+   |     ^^^^^^^ value used here after move
 ...
 LL |         _ if { (|| { let bar = b; *bar = false; })();
    |                 --             - variable moved due to use in closure
    |                 |
    |                 value moved into closure here
-LL |                      false } => { },
-LL |         &mut true => { println!("You might think we should get here"); },
-   |              ^^^^ value used here after move
 
 error: aborting due to previous error
 
index 5513c3d217e2a3c4a35b22c8ae2f7899106c81ba..14e1667038965b772576cbc3106e1b071bcc5d9a 100644 (file)
@@ -1,9 +1,3 @@
-error[E0507]: cannot move out of static item `settings_dir`
-  --> $DIR/issue-64453.rs:14:37
-   |
-LL |     let settings_data = from_string(settings_dir);
-   |                                     ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
-
 error: `Arguments::<'a>::new_v1` is not yet stable as a const fn
   --> $DIR/issue-64453.rs:4:31
    |
@@ -21,6 +15,12 @@ LL | static settings_dir: String = format!("");
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error[E0507]: cannot move out of static item `settings_dir`
+  --> $DIR/issue-64453.rs:14:37
+   |
+LL |     let settings_data = from_string(settings_dir);
+   |                                     ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
+
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0015, E0507.
index 3f092846dd4c03b9198a059d07052e8868a25630..7cdb16b282d540253dd756071d02611639dc3ef5 100644 (file)
@@ -2,12 +2,36 @@
 #![crate_type = "rlib"]
 
 pub fn f(b: &mut i32) {
-    g(&mut b);
+    //~^ NOTE the binding is already a mutable borrow
+    //~| NOTE the binding is already a mutable borrow
+    h(&mut b);
     //~^ ERROR cannot borrow
+    //~| NOTE cannot borrow as mutable
     //~| HELP try removing `&mut` here
     g(&mut &mut b);
     //~^ ERROR cannot borrow
+    //~| NOTE cannot borrow as mutable
     //~| HELP try removing `&mut` here
 }
 
-pub fn g(_: &mut i32) {}
+pub fn g(b: &mut i32) { //~ NOTE the binding is already a mutable borrow
+    h(&mut &mut b);
+    //~^ ERROR cannot borrow
+    //~| NOTE cannot borrow as mutable
+    //~| HELP try removing `&mut` here
+}
+
+pub fn h(_: &mut i32) {}
+
+trait Foo {
+    fn bar(&mut self);
+}
+
+impl Foo for &mut String {
+    fn bar(&mut self) {}
+}
+
+pub fn baz(f: &mut String) { //~ HELP consider making the binding mutable
+    f.bar(); //~ ERROR cannot borrow `f` as mutable, as it is not declared as mutable
+    //~^ NOTE cannot borrow as mutable
+}
index cb7355b2335965aa9490f0af4a25861a2a0f8302..e4c51bb77c9edca9b779010c70a92fda2aa7b675 100644 (file)
@@ -1,21 +1,65 @@
 error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:5:7
+  --> $DIR/mut-borrow-of-mut-ref.rs:7:7
    |
-LL |     g(&mut b);
-   |       ^^^^^^
-   |       |
-   |       cannot borrow as mutable
-   |       help: try removing `&mut` here
+LL |     h(&mut b);
+   |       ^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/mut-borrow-of-mut-ref.rs:4:13
+   |
+LL | pub fn f(b: &mut i32) {
+   |             ^^^^^^^^
+help: try removing `&mut` here
+   |
+LL -     h(&mut b);
+LL +     h(b);
+   | 
 
 error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
-  --> $DIR/mut-borrow-of-mut-ref.rs:8:12
+  --> $DIR/mut-borrow-of-mut-ref.rs:11:12
    |
 LL |     g(&mut &mut b);
-   |            ^^^^^^
-   |            |
-   |            cannot borrow as mutable
-   |            help: try removing `&mut` here
+   |            ^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/mut-borrow-of-mut-ref.rs:4:13
+   |
+LL | pub fn f(b: &mut i32) {
+   |             ^^^^^^^^
+help: try removing `&mut` here
+   |
+LL -     g(&mut &mut b);
+LL +     g(&mut b);
+   | 
+
+error[E0596]: cannot borrow `b` as mutable, as it is not declared as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:18:12
+   |
+LL |     h(&mut &mut b);
+   |            ^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/mut-borrow-of-mut-ref.rs:17:13
+   |
+LL | pub fn g(b: &mut i32) {
+   |             ^^^^^^^^
+help: try removing `&mut` here
+   |
+LL -     h(&mut &mut b);
+LL +     h(&mut b);
+   | 
+
+error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:35:5
+   |
+LL |     f.bar();
+   |     ^ cannot borrow as mutable
+   |
+help: consider making the binding mutable
+   |
+LL | pub fn baz(mut f: &mut String) {
+   |            +++
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/issue-87097.rs
deleted file mode 100644 (file)
index 241ddcb..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// run-pass
-// edition:2021
-
-enum Variant {
-    A,
-    B, //~ WARNING: variant is never constructed: `B`
-}
-
-struct A {
-    field: Variant,
-}
-
-fn discriminant_is_a_ref() {
-    let here = A { field: Variant::A };
-    let out_ref = &here.field;
-
-    || match out_ref { //~ WARNING: unused closure that must be used
-        Variant::A => (),
-        Variant::B => (),
-    };
-}
-
-fn discriminant_is_a_field() {
-    let here = A { field: Variant::A };
-
-    || match here.field { //~ WARNING: unused closure that must be used
-        Variant::A => (),
-        Variant::B => (),
-    };
-}
-
-fn main() {
-    discriminant_is_a_ref();
-    discriminant_is_a_field();
-}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr
deleted file mode 100644 (file)
index 38f2929..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-warning: variant is never constructed: `B`
-  --> $DIR/issue-87097.rs:6:5
-   |
-LL |     B,
-   |     ^
-   |
-   = note: `#[warn(dead_code)]` on by default
-
-warning: unused closure that must be used
-  --> $DIR/issue-87097.rs:17:5
-   |
-LL | /     || match out_ref {
-LL | |         Variant::A => (),
-LL | |         Variant::B => (),
-LL | |     };
-   | |______^
-   |
-   = note: `#[warn(unused_must_use)]` on by default
-   = note: closures are lazy and do nothing unless called
-
-warning: unused closure that must be used
-  --> $DIR/issue-87097.rs:26:5
-   |
-LL | /     || match here.field {
-LL | |         Variant::A => (),
-LL | |         Variant::B => (),
-LL | |     };
-   | |______^
-   |
-   = note: closures are lazy and do nothing unless called
-
-warning: 3 warnings emitted
-
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87426.rs b/src/test/ui/closures/2229_closure_analysis/issue-87426.rs
deleted file mode 100644 (file)
index 7450697..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-// edition:2021
-
-pub fn foo() {
-    let ref_x_ck = 123;
-    let _y = || match ref_x_ck {
-        2_000_000..=3_999_999 => { println!("A")}
-        _ => { println!("B")}
-    };
-}
-
-fn main() {
-    foo();
-}
index 5dc2cb7e71099e24ba380487b5f011f76a7b9a9e..d4f243ee3475f42c8f49829dd2acc741c7733094 100644 (file)
@@ -8,7 +8,7 @@ struct Props {
 
 fn main() {
     // Test 1
-    let props_2 = Props { //~ WARNING: unused variable: `props_2`
+    let props_2 = Props {
         field_1: 1,
         field_2: 1,
     };
index aa7012c3618c2e5038df8b45431cd902eb4c1c93..5828295fae33a77c9850839f04b2ff5c5a50d1c7 100644 (file)
@@ -1,11 +1,3 @@
-warning: unused variable: `props_2`
-  --> $DIR/issue-87987.rs:11:9
-   |
-LL |     let props_2 = Props {
-   |         ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_props_2`
-   |
-   = note: `#[warn(unused_variables)]` on by default
-
 warning: field is never read: `field_1`
   --> $DIR/issue-87987.rs:5:5
    |
@@ -20,5 +12,5 @@ warning: field is never read: `field_2`
 LL |     field_2: u32,
    |     ^^^^^^^^^^^^
 
-warning: 3 warnings emitted
+warning: 2 warnings emitted
 
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87988.rs b/src/test/ui/closures/2229_closure_analysis/issue-87988.rs
deleted file mode 100644 (file)
index 27e7fab..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// run-pass
-// edition:2021
-
-const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: i32 = 0x01;
-const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: i32 = 0x02;
-
-pub fn hotplug_callback(event: i32) {
-    let _ = || {
-        match event {
-            LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => (),
-            LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => (),
-            _ => (),
-        };
-    };
-}
-
-fn main() {
-    hotplug_callback(1);
-}
diff --git a/src/test/ui/closures/2229_closure_analysis/issue_88118.rs b/src/test/ui/closures/2229_closure_analysis/issue_88118.rs
new file mode 100644 (file)
index 0000000..453b7e0
--- /dev/null
@@ -0,0 +1,15 @@
+// Regression test for #88118. Used to ICE.
+//
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(capture_disjoint_fields)]
+
+fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
+    Box::new(move |value| {
+        (|_| handler.clone()())(value);
+        None
+    }) as Box<dyn Fn(i32) -> Option<i32>>;
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs
deleted file mode 100644 (file)
index 914ebbe..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-// run-pass
-// edition:2021
-
-const PATTERN_REF: &str = "Hello World";
-const NUMBER: i32 = 30;
-const NUMBER_POINTER: *const i32 = &NUMBER;
-
-pub fn edge_case_ref(event: &str) {
-    let _ = || {
-        match event {
-            PATTERN_REF => (),
-            _ => (),
-        };
-    };
-}
-
-pub fn edge_case_str(event: String) {
-    let _ = || {
-        match event.as_str() {
-            "hello" => (),
-            _ => (),
-        };
-    };
-}
-
-pub fn edge_case_raw_ptr(event: *const i32) {
-    let _ = || {
-        match event {
-            NUMBER_POINTER => (),
-            _ => (),
-        };
-    };
-}
-
-pub fn edge_case_char(event: char) {
-    let _ = || {
-        match event {
-            'a' => (),
-            _ => (),
-        };
-    };
-}
-
-fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs
new file mode 100644 (file)
index 0000000..4060c40
--- /dev/null
@@ -0,0 +1,10 @@
+#[non_exhaustive]
+pub enum E1 {}
+
+#[non_exhaustive]
+pub enum E2 { A, B }
+
+#[non_exhaustive]
+pub enum E3 { C }
+
+pub enum E4 { D }
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs
new file mode 100644 (file)
index 0000000..241ddcb
--- /dev/null
@@ -0,0 +1,35 @@
+// run-pass
+// edition:2021
+
+enum Variant {
+    A,
+    B, //~ WARNING: variant is never constructed: `B`
+}
+
+struct A {
+    field: Variant,
+}
+
+fn discriminant_is_a_ref() {
+    let here = A { field: Variant::A };
+    let out_ref = &here.field;
+
+    || match out_ref { //~ WARNING: unused closure that must be used
+        Variant::A => (),
+        Variant::B => (),
+    };
+}
+
+fn discriminant_is_a_field() {
+    let here = A { field: Variant::A };
+
+    || match here.field { //~ WARNING: unused closure that must be used
+        Variant::A => (),
+        Variant::B => (),
+    };
+}
+
+fn main() {
+    discriminant_is_a_ref();
+    discriminant_is_a_field();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
new file mode 100644 (file)
index 0000000..38f2929
--- /dev/null
@@ -0,0 +1,33 @@
+warning: variant is never constructed: `B`
+  --> $DIR/issue-87097.rs:6:5
+   |
+LL |     B,
+   |     ^
+   |
+   = note: `#[warn(dead_code)]` on by default
+
+warning: unused closure that must be used
+  --> $DIR/issue-87097.rs:17:5
+   |
+LL | /     || match out_ref {
+LL | |         Variant::A => (),
+LL | |         Variant::B => (),
+LL | |     };
+   | |______^
+   |
+   = note: `#[warn(unused_must_use)]` on by default
+   = note: closures are lazy and do nothing unless called
+
+warning: unused closure that must be used
+  --> $DIR/issue-87097.rs:26:5
+   |
+LL | /     || match here.field {
+LL | |         Variant::A => (),
+LL | |         Variant::B => (),
+LL | |     };
+   | |______^
+   |
+   = note: closures are lazy and do nothing unless called
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs
new file mode 100644 (file)
index 0000000..7450697
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+// edition:2021
+
+pub fn foo() {
+    let ref_x_ck = 123;
+    let _y = || match ref_x_ck {
+        2_000_000..=3_999_999 => { println!("A")}
+        _ => { println!("B")}
+    };
+}
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87988.rs
new file mode 100644 (file)
index 0000000..27e7fab
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+// edition:2021
+
+const LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED: i32 = 0x01;
+const LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT: i32 = 0x02;
+
+pub fn hotplug_callback(event: i32) {
+    let _ = || {
+        match event {
+            LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED => (),
+            LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT => (),
+            _ => (),
+        };
+    };
+}
+
+fn main() {
+    hotplug_callback(1);
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.rs
new file mode 100644 (file)
index 0000000..0a6d71c
--- /dev/null
@@ -0,0 +1,33 @@
+// edition:2021
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Opcode(pub u8);
+
+impl Opcode {
+    pub const OP1: Opcode = Opcode(0x1);
+}
+
+pub fn example1(msg_type: Opcode) -> impl FnMut(&[u8]) {
+    move |i| match msg_type {
+    //~^ ERROR: non-exhaustive patterns: `Opcode(0_u8)` and `Opcode(2_u8..=u8::MAX)` not covered
+        Opcode::OP1 => unimplemented!(),
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Opcode2(Opcode);
+
+impl Opcode2 {
+    pub const OP2: Opcode2 = Opcode2(Opcode(0x1));
+}
+
+
+pub fn example2(msg_type: Opcode2) -> impl FnMut(&[u8]) {
+
+    move |i| match msg_type {
+    //~^ ERROR: non-exhaustive patterns: `Opcode2(Opcode(0_u8))` and `Opcode2(Opcode(2_u8..=u8::MAX))` not covered
+        Opcode2::OP2=> unimplemented!(),
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-88331.stderr
new file mode 100644 (file)
index 0000000..f02d234
--- /dev/null
@@ -0,0 +1,27 @@
+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: the matched value is of type `Opcode`
+
+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: the matched value is of type `Opcode2`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_1.rs
new file mode 100644 (file)
index 0000000..914ebbe
--- /dev/null
@@ -0,0 +1,44 @@
+// run-pass
+// edition:2021
+
+const PATTERN_REF: &str = "Hello World";
+const NUMBER: i32 = 30;
+const NUMBER_POINTER: *const i32 = &NUMBER;
+
+pub fn edge_case_ref(event: &str) {
+    let _ = || {
+        match event {
+            PATTERN_REF => (),
+            _ => (),
+        };
+    };
+}
+
+pub fn edge_case_str(event: String) {
+    let _ = || {
+        match event.as_str() {
+            "hello" => (),
+            _ => (),
+        };
+    };
+}
+
+pub fn edge_case_raw_ptr(event: *const i32) {
+    let _ = || {
+        match event {
+            NUMBER_POINTER => (),
+            _ => (),
+        };
+    };
+}
+
+pub fn edge_case_char(event: char) {
+    let _ = || {
+        match event {
+            'a' => (),
+            _ => (),
+        };
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.rs
new file mode 100644 (file)
index 0000000..ae724f9
--- /dev/null
@@ -0,0 +1,37 @@
+// edition:2021
+
+enum SingleVariant {
+    A
+}
+
+struct TestStruct {
+    x: i32,
+    y: i32,
+    z: i32,
+}
+
+fn edge_case_if() {
+    let sv = SingleVariant::A;
+    let condition = true;
+    // sv should not be captured as it is a SingleVariant
+    let _a = || {
+        match sv {
+            SingleVariant::A if condition => (),
+            _ => ()
+        }
+    };
+    let mut mut_sv = sv;
+    _a();
+
+    // ts should be captured
+    let ts = TestStruct { x: 1, y: 1, z: 1 };
+    let _b = || { match ts {
+        TestStruct{ x: 1, .. } => (),
+        _ => ()
+    }};
+    let mut mut_ts = ts;
+    //~^ ERROR: cannot move out of `ts` because it is borrowed
+    _b();
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases_2.stderr
new file mode 100644 (file)
index 0000000..1e42d73
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0505]: cannot move out of `ts` because it is borrowed
+  --> $DIR/match-edge-cases_2.rs:32:22
+   |
+LL |     let _b = || { match ts {
+   |              --         -- borrow occurs due to use in closure
+   |              |
+   |              borrow of `ts` occurs here
+...
+LL |     let mut mut_ts = ts;
+   |                      ^^ move out of `ts` occurs here
+LL |
+LL |     _b();
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0505`.
diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs
new file mode 100644 (file)
index 0000000..318673e
--- /dev/null
@@ -0,0 +1,54 @@
+// edition:2021
+
+// aux-build:match_non_exhaustive_lib.rs
+
+/* The error message for non-exhaustive matches on non-local enums
+ * marked as non-exhaustive should mention the fact that the enum
+ * is marked as non-exhaustive (issue #85227).
+ */
+
+// Ignore non_exhaustive in the same crate
+#[non_exhaustive]
+enum L1 { A, B }
+enum L2 { C }
+
+extern crate match_non_exhaustive_lib;
+use match_non_exhaustive_lib::{E1, E2, E3, E4};
+
+fn foo() -> (L1, L2) {todo!()}
+fn bar() -> (E1, E2, E3, E4) {todo!()}
+
+fn main() {
+    let (l1, l2) = foo();
+    // No error for enums defined in this crate
+    let _a = || { match l1 { L1::A => (), L1::B => () } };
+    // (except if the match is already non-exhaustive)
+    let _b = || { match l1 { L1::A => () } };
+    //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004]
+
+    // l2 should not be captured as it is a non-exhaustive SingleVariant
+    // defined in this crate
+    let _c = || { match l2 { L2::C => (), _ => () }  };
+    let mut mut_l2 = l2;
+    _c();
+
+    // E1 is not visibly uninhabited from here
+    let (e1, e2, e3, e4) = bar();
+    let _d = || { match e1 {} };
+    //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004]
+    let _e = || { match e2 { E2::A => (), E2::B => () } };
+    //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004]
+    let _f = || { match e2 { E2::A => (), E2::B => (), _ => () }  };
+
+    // e3 should be captured as it is a non-exhaustive SingleVariant
+    // defined in another crate
+    let _g = || { match e3 { E3::C => (), _ => () }  };
+    let mut mut_e3 = e3;
+    //~^ ERROR: cannot move out of `e3` because it is borrowed
+    _g();
+
+    // e4 should not be captured as it is a SingleVariant
+    let _h = || { match e4 { E4::D => (), _ => () }  };
+    let mut mut_e4 = e4;
+    _h();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr
new file mode 100644 (file)
index 0000000..91ffe1a
--- /dev/null
@@ -0,0 +1,50 @@
+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: the matched value is of type `L1`
+
+error[E0004]: non-exhaustive patterns: type `E1` is non-empty
+  --> $DIR/non-exhaustive-match.rs:37:25
+   |
+LL |     let _d = || { match e1 {} };
+   |                         ^^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `E1`, which is marked as non-exhaustive
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/non-exhaustive-match.rs:39:25
+   |
+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: the matched value is of type `E2`, which is marked as non-exhaustive
+
+error[E0505]: cannot move out of `e3` because it is borrowed
+  --> $DIR/non-exhaustive-match.rs:46:22
+   |
+LL |     let _g = || { match e3 { E3::C => (), _ => () }  };
+   |              --         -- borrow occurs due to use in closure
+   |              |
+   |              borrow of `e3` occurs here
+LL |     let mut mut_e3 = e3;
+   |                      ^^ move out of `e3` occurs here
+LL |
+LL |     _g();
+   |     -- borrow later used here
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0004, E0505.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs
new file mode 100644 (file)
index 0000000..0f288ff
--- /dev/null
@@ -0,0 +1,82 @@
+// edition:2021
+
+#![feature(never_type)]
+
+// Should fake read the discriminant and throw an error
+fn test1() {
+    let x: !;
+    let c1 = || match x { };
+    //~^ ERROR: use of possibly-uninitialized variable: `x`
+}
+
+// Should fake read the discriminant and throw an error
+fn test2() {
+    let x: !;
+    let c2 = || match x { _ => () };
+    //~^ ERROR: borrow of possibly-uninitialized variable: `x`
+}
+
+// Testing single variant patterns
+enum SingleVariant {
+    Points(u32)
+}
+
+// Should fake read the discriminant and throw an error
+fn test3() {
+    let variant: !;
+    let c = || {
+    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
+        match variant {
+            SingleVariant::Points(_) => {}
+        }
+    };
+    c();
+}
+
+// Should fake read the discriminant and throw an error
+fn test4() {
+    let variant: !;
+    let c = || {
+    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
+        match variant {
+            SingleVariant::Points(a) => {
+                println!("{:?}", a);
+            }
+        }
+    };
+    c();
+}
+
+fn test5() {
+    let t: !;
+    let g: !;
+
+    let a = || {
+        match g { };
+        //~^ ERROR: use of possibly-uninitialized variable: `g`
+        let c = ||  {
+            match t { };
+            //~^ ERROR: use of possibly-uninitialized variable: `t`
+        };
+
+        c();
+    };
+
+}
+
+// Should fake read the discriminant and throw an error
+fn test6() {
+    let x: u8;
+    let c1 = || match x { };
+    //~^ ERROR: use of possibly-uninitialized variable: `x`
+    //~| ERROR: non-exhaustive patterns: type `u8` is non-empty
+}
+
+fn main() {
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
new file mode 100644 (file)
index 0000000..45641ea
--- /dev/null
@@ -0,0 +1,63 @@
+error[E0004]: non-exhaustive patterns: type `u8` is non-empty
+  --> $DIR/pattern-matching-should-fail.rs:70:23
+   |
+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`
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/pattern-matching-should-fail.rs:8:23
+   |
+LL |     let c1 = || match x { };
+   |                       ^ use of possibly-uninitialized `x`
+
+error[E0381]: borrow of possibly-uninitialized variable: `x`
+  --> $DIR/pattern-matching-should-fail.rs:15:14
+   |
+LL |     let c2 = || match x { _ => () };
+   |              ^^       - borrow occurs due to use in closure
+   |              |
+   |              use of possibly-uninitialized `x`
+
+error[E0381]: borrow of possibly-uninitialized variable: `variant`
+  --> $DIR/pattern-matching-should-fail.rs:27:13
+   |
+LL |     let c = || {
+   |             ^^ use of possibly-uninitialized `variant`
+LL |
+LL |         match variant {
+   |               ------- borrow occurs due to use in closure
+
+error[E0381]: borrow of possibly-uninitialized variable: `variant`
+  --> $DIR/pattern-matching-should-fail.rs:39:13
+   |
+LL |     let c = || {
+   |             ^^ use of possibly-uninitialized `variant`
+LL |
+LL |         match variant {
+   |               ------- borrow occurs due to use in closure
+
+error[E0381]: use of possibly-uninitialized variable: `g`
+  --> $DIR/pattern-matching-should-fail.rs:55:15
+   |
+LL |         match g { };
+   |               ^ use of possibly-uninitialized `g`
+
+error[E0381]: use of possibly-uninitialized variable: `t`
+  --> $DIR/pattern-matching-should-fail.rs:58:19
+   |
+LL |             match t { };
+   |                   ^ use of possibly-uninitialized `t`
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/pattern-matching-should-fail.rs:70:23
+   |
+LL |     let c1 = || match x { };
+   |                       ^ use of possibly-uninitialized `x`
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0004, E0381.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
new file mode 100644 (file)
index 0000000..56f5ac4
--- /dev/null
@@ -0,0 +1,137 @@
+// edition:2021
+
+#![feature(rustc_attrs)]
+
+// Should capture the discriminant since a variant of a multivariant enum is
+// mentioned in the match arm; the discriminant is captured by the closure regardless
+// of if it creates a binding
+fn test_1_should_capture() {
+    let variant = Some(2229);
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match variant {
+        //~^ NOTE: Capturing variant[] -> ImmBorrow
+        //~| NOTE: Min Capture variant[] -> ImmBorrow
+            Some(_) => {}
+            _ => {}
+        }
+    };
+    c();
+}
+
+// Should not capture the discriminant since only a wildcard is mentioned in the
+// match arm
+fn test_2_should_not_capture() {
+    let variant = Some(2229);
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ First Pass analysis includes:
+        match variant {
+            _ => {}
+        }
+    };
+    c();
+}
+
+// Testing single variant patterns
+enum SingleVariant {
+    Points(u32)
+}
+
+// Should not capture the discriminant since the single variant mentioned
+// in the match arm does not trigger a binding
+fn test_3_should_not_capture_single_variant() {
+    let variant = SingleVariant::Points(1);
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ First Pass analysis includes:
+        match variant {
+            SingleVariant::Points(_) => {}
+        }
+    };
+    c();
+}
+
+// Should not capture the discriminant since the single variant mentioned
+// in the match arm does not trigger a binding
+fn test_6_should_capture_single_variant() {
+    let variant = SingleVariant::Points(1);
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match variant {
+            //~^ NOTE: Capturing variant[] -> ImmBorrow
+            //~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow
+            //~| NOTE: Min Capture variant[] -> ImmBorrow
+            SingleVariant::Points(a) => {
+                println!("{:?}", a);
+            }
+        }
+    };
+    c();
+}
+
+// Should not capture the discriminant since only wildcards are mentioned in the
+// match arm
+fn test_4_should_not_capture_array() {
+    let array: [i32; 3] = [0; 3];
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ First Pass analysis includes:
+        match array {
+            [_,_,_] => {}
+        }
+    };
+    c();
+}
+
+// Testing MultiVariant patterns
+enum MVariant {
+    A,
+    B,
+    C,
+}
+
+// Should capture the discriminant since a variant of the multi variant enum is
+// mentioned in the match arm; the discriminant is captured by the closure
+// regardless of if it creates a binding
+fn test_5_should_capture_multi_variant() {
+    let variant = MVariant::A;
+    let c =  #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+    || {
+    //~^ First Pass analysis includes:
+    //~| Min Capture analysis includes:
+        match variant {
+        //~^ NOTE: Capturing variant[] -> ImmBorrow
+        //~| NOTE: Min Capture variant[] -> ImmBorrow
+            MVariant::A => {}
+            _ => {}
+        }
+    };
+    c();
+}
+
+fn main() {
+    test_1_should_capture();
+    test_2_should_not_capture();
+    test_3_should_not_capture_single_variant();
+    test_6_should_capture_single_variant();
+    test_4_should_not_capture_array();
+    test_5_should_capture_multi_variant();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
new file mode 100644 (file)
index 0000000..4608133
--- /dev/null
@@ -0,0 +1,203 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:10:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:31:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:52:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:68:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:90:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/patterns-capture-analysis.rs:114:14
+   |
+LL |     let c =  #[rustc_capture_analysis]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:14:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:17:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:14:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:17:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:34:5
+   |
+LL | /     || {
+LL | |
+LL | |         match variant {
+LL | |             _ => {}
+LL | |         }
+LL | |     };
+   | |_____^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:55:5
+   |
+LL | /     || {
+LL | |
+LL | |         match variant {
+LL | |             SingleVariant::Points(_) => {}
+LL | |         }
+LL | |     };
+   | |_____^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:71:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:74:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+note: Capturing variant[(0, 0)] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:74:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:71:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:74:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:93:5
+   |
+LL | /     || {
+LL | |
+LL | |         match array {
+LL | |             [_,_,_] => {}
+LL | |         }
+LL | |     };
+   | |_____^
+
+error: First Pass analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:117:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Capturing variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:120:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: Min Capture analysis includes:
+  --> $DIR/patterns-capture-analysis.rs:117:5
+   |
+LL | /     || {
+LL | |
+LL | |
+LL | |         match variant {
+...  |
+LL | |         }
+LL | |     };
+   | |_____^
+   |
+note: Min Capture variant[] -> ImmBorrow
+  --> $DIR/patterns-capture-analysis.rs:120:15
+   |
+LL |         match variant {
+   |               ^^^^^^^
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.fixed
new file mode 100644 (file)
index 0000000..f91454a
--- /dev/null
@@ -0,0 +1,25 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_compatibility)]
+
+macro_rules! m {
+    (@ $body:expr) => {{
+        let f = || $body;
+        //~^ WARNING: drop order
+        f();
+    }};
+    ($body:block) => {{
+        m!(@ $body);
+    }};
+}
+
+fn main() {
+    let a = (1.to_string(), 2.to_string());
+    m!({
+        let _ = &a;
+        //~^ HELP: add a dummy
+        let x = a.0;
+        println!("{}", x);
+    });
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.rs
new file mode 100644 (file)
index 0000000..5a1026d
--- /dev/null
@@ -0,0 +1,24 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_compatibility)]
+
+macro_rules! m {
+    (@ $body:expr) => {{
+        let f = || $body;
+        //~^ WARNING: drop order
+        f();
+    }};
+    ($body:block) => {{
+        m!(@ $body);
+    }};
+}
+
+fn main() {
+    let a = (1.to_string(), 2.to_string());
+    m!({
+        //~^ HELP: add a dummy
+        let x = a.0;
+        println!("{}", x);
+    });
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr
new file mode 100644 (file)
index 0000000..e6e5598
--- /dev/null
@@ -0,0 +1,37 @@
+warning: changes to closure capture in Rust 2021 will affect drop order
+  --> $DIR/closure-body-macro-fragment.rs:8:17
+   |
+LL |           let f = || $body;
+   |  _________________^
+LL | |
+LL | |         f();
+LL | |     }};
+   | |     - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
+LL | |     ($body:block) => {{
+LL | |         m!(@ $body);
+   | |__________________^
+...
+LL | /     m!({
+LL | |
+LL | |         let x = a.0;
+   | |                 --- in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
+LL | |         println!("{}", x);
+LL | |     });
+   | |_______- in this macro invocation
+   |
+note: the lint level is defined here
+  --> $DIR/closure-body-macro-fragment.rs:4:9
+   |
+LL | #![warn(rust_2021_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+   = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: add a dummy let to cause `a` to be fully captured
+   |
+LL ~     m!({
+LL +         let _ = &a;
+   |
+
+warning: 1 warning emitted
+
index 6b49293e6d3fb735e70cfafb12000352754fe43c..b542fa2430c348cdf0deb7b9394071e302ba1771 100644 (file)
@@ -35,7 +35,7 @@ fn simple_ref() {
     //~| ERROR: Min Capture analysis includes:
         *ref_s += 10;
         //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
-        //~| NOTE: Min Capture ref_s[Deref] -> MutBorrow
+        //~| NOTE: Min Capture ref_s[] -> ByValue
     };
     c();
 }
@@ -56,7 +56,7 @@ fn struct_contains_ref_to_another_struct_1() {
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new s".into();
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
-        //~| NOTE: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
+        //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
     c();
@@ -79,7 +79,7 @@ fn struct_contains_ref_to_another_struct_2() {
     //~| ERROR: Min Capture analysis includes:
         let _t = t.0.0;
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(0, 0),Deref] -> ImmBorrow
+        //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
     c();
@@ -175,7 +175,7 @@ fn box_mut_1() {
     //~| First Pass analysis includes:
     //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
     //~| Min Capture analysis includes:
-    //~| NOTE: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Min Capture box_p_foo[] -> ByValue
 }
 
 // Ensure that even in move closures, if the data is not owned by the root variable
@@ -192,7 +192,7 @@ fn box_mut_2() {
     //~| First Pass analysis includes:
     //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
     //~| Min Capture analysis includes:
-    //~| NOTE: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Min Capture p_foo[] -> ByValue
 }
 
 // Test that move closures can take ownership of Copy type
index b99b451a1711b3981c4ba23c3e3ee4351b86d734..fd80e05c6893fb057ca452a19dcc0ed552deabf3 100644 (file)
@@ -187,7 +187,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture ref_s[Deref] -> MutBorrow
+note: Min Capture ref_s[] -> ByValue
   --> $DIR/move_closure.rs:36:9
    |
 LL |         *ref_s += 10;
@@ -223,7 +223,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref,(0, 0)] -> MutBorrow
+note: Min Capture t[(0, 0)] -> ByValue
   --> $DIR/move_closure.rs:57:9
    |
 LL |         t.0.0 = "new s".into();
@@ -259,7 +259,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0),Deref] -> ImmBorrow
+note: Min Capture t[(0, 0)] -> ByValue
   --> $DIR/move_closure.rs:80:18
    |
 LL |         let _t = t.0.0;
@@ -427,7 +427,7 @@ error: Min Capture analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: Min Capture box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Min Capture box_p_foo[] -> ByValue
   --> $DIR/move_closure.rs:172:47
    |
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
@@ -451,7 +451,7 @@ error: Min Capture analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^
    |
-note: Min Capture p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Min Capture p_foo[] -> ByValue
   --> $DIR/move_closure.rs:189:47
    |
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs
deleted file mode 100644 (file)
index 0f288ff..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// edition:2021
-
-#![feature(never_type)]
-
-// Should fake read the discriminant and throw an error
-fn test1() {
-    let x: !;
-    let c1 = || match x { };
-    //~^ ERROR: use of possibly-uninitialized variable: `x`
-}
-
-// Should fake read the discriminant and throw an error
-fn test2() {
-    let x: !;
-    let c2 = || match x { _ => () };
-    //~^ ERROR: borrow of possibly-uninitialized variable: `x`
-}
-
-// Testing single variant patterns
-enum SingleVariant {
-    Points(u32)
-}
-
-// Should fake read the discriminant and throw an error
-fn test3() {
-    let variant: !;
-    let c = || {
-    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
-        match variant {
-            SingleVariant::Points(_) => {}
-        }
-    };
-    c();
-}
-
-// Should fake read the discriminant and throw an error
-fn test4() {
-    let variant: !;
-    let c = || {
-    //~^ ERROR: borrow of possibly-uninitialized variable: `variant`
-        match variant {
-            SingleVariant::Points(a) => {
-                println!("{:?}", a);
-            }
-        }
-    };
-    c();
-}
-
-fn test5() {
-    let t: !;
-    let g: !;
-
-    let a = || {
-        match g { };
-        //~^ ERROR: use of possibly-uninitialized variable: `g`
-        let c = ||  {
-            match t { };
-            //~^ ERROR: use of possibly-uninitialized variable: `t`
-        };
-
-        c();
-    };
-
-}
-
-// Should fake read the discriminant and throw an error
-fn test6() {
-    let x: u8;
-    let c1 = || match x { };
-    //~^ ERROR: use of possibly-uninitialized variable: `x`
-    //~| ERROR: non-exhaustive patterns: type `u8` is non-empty
-}
-
-fn main() {
-    test1();
-    test2();
-    test3();
-    test4();
-    test5();
-    test6();
-}
diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr
deleted file mode 100644 (file)
index 45641ea..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/pattern-matching-should-fail.rs:70:23
-   |
-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`
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:8:23
-   |
-LL |     let c1 = || match x { };
-   |                       ^ use of possibly-uninitialized `x`
-
-error[E0381]: borrow of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:15:14
-   |
-LL |     let c2 = || match x { _ => () };
-   |              ^^       - borrow occurs due to use in closure
-   |              |
-   |              use of possibly-uninitialized `x`
-
-error[E0381]: borrow of possibly-uninitialized variable: `variant`
-  --> $DIR/pattern-matching-should-fail.rs:27:13
-   |
-LL |     let c = || {
-   |             ^^ use of possibly-uninitialized `variant`
-LL |
-LL |         match variant {
-   |               ------- borrow occurs due to use in closure
-
-error[E0381]: borrow of possibly-uninitialized variable: `variant`
-  --> $DIR/pattern-matching-should-fail.rs:39:13
-   |
-LL |     let c = || {
-   |             ^^ use of possibly-uninitialized `variant`
-LL |
-LL |         match variant {
-   |               ------- borrow occurs due to use in closure
-
-error[E0381]: use of possibly-uninitialized variable: `g`
-  --> $DIR/pattern-matching-should-fail.rs:55:15
-   |
-LL |         match g { };
-   |               ^ use of possibly-uninitialized `g`
-
-error[E0381]: use of possibly-uninitialized variable: `t`
-  --> $DIR/pattern-matching-should-fail.rs:58:19
-   |
-LL |             match t { };
-   |                   ^ use of possibly-uninitialized `t`
-
-error[E0381]: use of possibly-uninitialized variable: `x`
-  --> $DIR/pattern-matching-should-fail.rs:70:23
-   |
-LL |     let c1 = || match x { };
-   |                       ^ use of possibly-uninitialized `x`
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0004, E0381.
-For more information about an error, try `rustc --explain E0004`.
diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs
deleted file mode 100644 (file)
index 56f5ac4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-// edition:2021
-
-#![feature(rustc_attrs)]
-
-// Should capture the discriminant since a variant of a multivariant enum is
-// mentioned in the match arm; the discriminant is captured by the closure regardless
-// of if it creates a binding
-fn test_1_should_capture() {
-    let variant = Some(2229);
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-
-    || {
-    //~^ First Pass analysis includes:
-    //~| Min Capture analysis includes:
-        match variant {
-        //~^ NOTE: Capturing variant[] -> ImmBorrow
-        //~| NOTE: Min Capture variant[] -> ImmBorrow
-            Some(_) => {}
-            _ => {}
-        }
-    };
-    c();
-}
-
-// Should not capture the discriminant since only a wildcard is mentioned in the
-// match arm
-fn test_2_should_not_capture() {
-    let variant = Some(2229);
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-    || {
-    //~^ First Pass analysis includes:
-        match variant {
-            _ => {}
-        }
-    };
-    c();
-}
-
-// Testing single variant patterns
-enum SingleVariant {
-    Points(u32)
-}
-
-// Should not capture the discriminant since the single variant mentioned
-// in the match arm does not trigger a binding
-fn test_3_should_not_capture_single_variant() {
-    let variant = SingleVariant::Points(1);
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-    || {
-    //~^ First Pass analysis includes:
-        match variant {
-            SingleVariant::Points(_) => {}
-        }
-    };
-    c();
-}
-
-// Should not capture the discriminant since the single variant mentioned
-// in the match arm does not trigger a binding
-fn test_6_should_capture_single_variant() {
-    let variant = SingleVariant::Points(1);
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-    || {
-    //~^ First Pass analysis includes:
-    //~| Min Capture analysis includes:
-        match variant {
-            //~^ NOTE: Capturing variant[] -> ImmBorrow
-            //~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow
-            //~| NOTE: Min Capture variant[] -> ImmBorrow
-            SingleVariant::Points(a) => {
-                println!("{:?}", a);
-            }
-        }
-    };
-    c();
-}
-
-// Should not capture the discriminant since only wildcards are mentioned in the
-// match arm
-fn test_4_should_not_capture_array() {
-    let array: [i32; 3] = [0; 3];
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-    || {
-    //~^ First Pass analysis includes:
-        match array {
-            [_,_,_] => {}
-        }
-    };
-    c();
-}
-
-// Testing MultiVariant patterns
-enum MVariant {
-    A,
-    B,
-    C,
-}
-
-// Should capture the discriminant since a variant of the multi variant enum is
-// mentioned in the match arm; the discriminant is captured by the closure
-// regardless of if it creates a binding
-fn test_5_should_capture_multi_variant() {
-    let variant = MVariant::A;
-    let c =  #[rustc_capture_analysis]
-    //~^ ERROR: attributes on expressions are experimental
-    //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
-    || {
-    //~^ First Pass analysis includes:
-    //~| Min Capture analysis includes:
-        match variant {
-        //~^ NOTE: Capturing variant[] -> ImmBorrow
-        //~| NOTE: Min Capture variant[] -> ImmBorrow
-            MVariant::A => {}
-            _ => {}
-        }
-    };
-    c();
-}
-
-fn main() {
-    test_1_should_capture();
-    test_2_should_not_capture();
-    test_3_should_not_capture_single_variant();
-    test_6_should_capture_single_variant();
-    test_4_should_not_capture_array();
-    test_5_should_capture_multi_variant();
-}
diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr
deleted file mode 100644 (file)
index 4608133..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:10:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:31:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:52:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:68:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:90:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error[E0658]: attributes on expressions are experimental
-  --> $DIR/patterns-capture-analysis.rs:114:14
-   |
-LL |     let c =  #[rustc_capture_analysis]
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
-   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:14:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:17:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:14:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:17:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:34:5
-   |
-LL | /     || {
-LL | |
-LL | |         match variant {
-LL | |             _ => {}
-LL | |         }
-LL | |     };
-   | |_____^
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:55:5
-   |
-LL | /     || {
-LL | |
-LL | |         match variant {
-LL | |             SingleVariant::Points(_) => {}
-LL | |         }
-LL | |     };
-   | |_____^
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:71:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-note: Capturing variant[(0, 0)] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:71:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:74:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:93:5
-   |
-LL | /     || {
-LL | |
-LL | |         match array {
-LL | |             [_,_,_] => {}
-LL | |         }
-LL | |     };
-   | |_____^
-
-error: First Pass analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:117:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Capturing variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:120:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: Min Capture analysis includes:
-  --> $DIR/patterns-capture-analysis.rs:117:5
-   |
-LL | /     || {
-LL | |
-LL | |
-LL | |         match variant {
-...  |
-LL | |         }
-LL | |     };
-   | |_____^
-   |
-note: Min Capture variant[] -> ImmBorrow
-  --> $DIR/patterns-capture-analysis.rs:120:15
-   |
-LL |         match variant {
-   |               ^^^^^^^
-
-error: aborting due to 15 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 07adbee03f968c71009f644ee0793148e72ff743..dacc2c616b8b6936dedeedabd2d30f5a0946cdd3 100644 (file)
@@ -43,7 +43,6 @@ fn test3() {
 
 fn test4() {
     let t = (String::from("Hello"), String::from("World"));
-    //~^ WARN unused variable: `t`
 
     let c = ||  {
         let (_, _) = t;
@@ -81,9 +80,7 @@ fn test7() {
 
 fn test8() {
     let x = 0;
-    //~^ WARN unused variable: `x`
     let tup = (1, 2);
-    //~^ WARN unused variable: `tup`
     let p = Point { x: 10, y: 20 };
 
     let c = || {
index 6523f2b34d537c076a53d36e20a5b633c06b6878..7706f68ba5b44ba22d74805093db8c0e68877c62 100644 (file)
@@ -29,29 +29,11 @@ warning: unused variable: `t2`
 LL |         let (_, t2) = t;
    |                 ^^ help: if this is intentional, prefix it with an underscore: `_t2`
 
-warning: unused variable: `t`
-  --> $DIR/destructure_patterns.rs:45:9
-   |
-LL |     let t = (String::from("Hello"), String::from("World"));
-   |         ^ help: if this is intentional, prefix it with an underscore: `_t`
-
 warning: unused variable: `x`
-  --> $DIR/destructure_patterns.rs:91:21
+  --> $DIR/destructure_patterns.rs:88:21
    |
 LL |         let Point { x, y } = p;
    |                     ^ help: try ignoring the field: `x: _`
 
-warning: unused variable: `x`
-  --> $DIR/destructure_patterns.rs:83:9
-   |
-LL |     let x = 0;
-   |         ^ help: if this is intentional, prefix it with an underscore: `_x`
-
-warning: unused variable: `tup`
-  --> $DIR/destructure_patterns.rs:85:9
-   |
-LL |     let tup = (1, 2);
-   |         ^^^ help: if this is intentional, prefix it with an underscore: `_tup`
-
-warning: 8 warnings emitted
+warning: 5 warnings emitted
 
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88372.rs
new file mode 100644 (file)
index 0000000..25fbb6c
--- /dev/null
@@ -0,0 +1,19 @@
+// edition:2021
+// run-pass
+
+
+fn solve<F>(validate: F) -> Option<u64>
+where
+    F: Fn(&mut [i8; 1]),
+{
+    let mut position: [i8; 1] = [1];
+    Some(0).map(|_| {
+        validate(&mut position);
+        let [_x] = position;
+        0
+    })
+}
+
+fn main() {
+    solve(|_| ());
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/issue-88431.rs
new file mode 100644 (file)
index 0000000..9996205
--- /dev/null
@@ -0,0 +1,59 @@
+// edition:2021
+// check-pass
+
+use std::collections::HashMap;
+use std::future::Future;
+use std::pin::Pin;
+
+pub struct GameMode {}
+
+struct GameStateManager<'a> {
+    gamestate_stack: Vec<Box<dyn GameState<'a> + 'a>>,
+}
+
+pub trait GameState<'a> {}
+
+async fn construct_gamestate_replay<'a>(
+    _gamemode: &GameMode,
+    _factory: &mut GameStateManager<'a>,
+) -> Box<dyn GameState<'a> + 'a> {
+    unimplemented!()
+}
+
+type FutureGameState<'a, 'b> = Pin<Box<dyn Future<Output = Box<dyn GameState<'a> + 'a>> + 'b>>;
+
+struct MenuOption<'a> {
+    command: Box<dyn for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a>,
+}
+
+impl<'a> MenuOption<'a> {
+    fn new(
+        _command: impl for<'b> Fn(&'b mut GameStateManager<'a>) -> FutureGameState<'a, 'b> + 'a,
+    ) -> Self {
+        unimplemented!()
+    }
+}
+
+struct MenuState<'a> {
+    options: Vec<MenuOption<'a>>,
+}
+
+impl<'a> GameState<'a> for MenuState<'a> {}
+
+pub async fn get_replay_menu<'a>(
+    gamemodes: &'a HashMap<&str, GameMode>,
+) -> Box<dyn GameState<'a> + 'a> {
+    let recordings: Vec<String> = vec![];
+    let _ = recordings
+        .into_iter()
+        .map(|entry| {
+            MenuOption::new(move |f| {
+                Box::pin(construct_gamestate_replay(&gamemodes[entry.as_str()], f))
+            })
+        })
+        .collect::<Vec<_>>();
+
+    todo!()
+}
+
+fn main() {}
index e1b61e85ec1927d18444a778bcb188820ce67bee..f76965bdd3fccbf4711438a5739ce35b9eabeed0 100644 (file)
@@ -56,28 +56,6 @@ fn no_ref_nested() {
     c();
 }
 
-struct A<'a>(&'a mut String,  &'a mut String);
-// Test that reborrowing works as expected for move closures
-// by attempting a disjoint capture through a reference.
-fn disjoint_via_ref() {
-    let mut x = String::new();
-    let mut y = String::new();
-
-    let mut a = A(&mut x, &mut y);
-    let a = &mut a;
-
-    let mut c1 = move || {
-        a.0.truncate(0);
-    };
-
-    let mut c2 = move || {
-        a.1.truncate(0);
-    };
-
-    c1();
-    c2();
-}
-
 // Test that even if a path is moved into the closure, the closure is not FnOnce
 // if the path is not moved by the closure call.
 fn data_moved_but_not_fn_once() {
@@ -109,7 +87,6 @@ fn main() {
     no_ref();
     no_ref_nested();
 
-    disjoint_via_ref();
     data_moved_but_not_fn_once();
 
     returned_closure_owns_copy_type_data();
index 909c33f642d31f581e7fafb31ac18b0d04a3293b..acc1c6ae1225d2b411274145a973b607eac89aa7 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 trait T<'x> {
     type V;
 }
@@ -8,6 +10,4 @@ impl<'g> T<'g> for u32 {
 
 fn main() {
     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
-    //~^ ERROR: type mismatch in closure arguments
-    //~| ERROR: size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
 }
diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr
deleted file mode 100644 (file)
index 06477ef..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-41366.rs:10:5
-   |
-LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
-   |     ^^------^
-   |     | |
-   |     | found signature of `fn(u16) -> _`
-   |     expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
-   |
-   = note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`
-
-error[E0277]: the size for values of type `<u32 as T<'_>>::V` cannot be known at compilation time
-  --> $DIR/issue-41366.rs:10:8
-   |
-LL |     (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
-   |        ^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `<u32 as T<'_>>::V`
-   = help: unsized fn params are gated as an unstable feature
-help: consider further restricting the associated type
-   |
-LL | fn main() where <u32 as T<'_>>::V: Sized {
-   |           ++++++++++++++++++++++++++++++
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     (&|&_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
-   |        +
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closures/issue-87814-1.rs b/src/test/ui/closures/issue-87814-1.rs
new file mode 100644 (file)
index 0000000..5cf01dd
--- /dev/null
@@ -0,0 +1,8 @@
+// check-pass
+fn main() {
+    let mut schema_all = vec![];
+    (0..42).for_each(|_x| match Err(()) as Result<(), _> {
+        Ok(()) => schema_all.push(()),
+        Err(_) => (),
+    });
+}
diff --git a/src/test/ui/closures/issue-87814-2.rs b/src/test/ui/closures/issue-87814-2.rs
new file mode 100644 (file)
index 0000000..7a5facd
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+#![feature(try_reserve)]
+
+fn main() {
+    let mut schema_all: (Vec<String>, Vec<String>) = (vec![], vec![]);
+
+    let _c = || match schema_all.0.try_reserve(1) as Result<(), _> {
+        Ok(()) => (),
+        Err(_) => (),
+    };
+}
index f3edf1c350f508d992573b349066f4b91ded2ddc..97f3c759355d45327c18d917d05dd1ede01f43eb 100644 (file)
@@ -14,7 +14,7 @@ error[E0391]: cycle detected when building specialization graph of trait `Trait`
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
    |
-   = note: ...which again requires building specialization graph of trait `Trait`, completing the cycle
+   = note: ...which immediately requires building specialization graph of trait `Trait` again
 note: cycle used when coherence checking all impls of trait `Trait`
   --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
    |
index 6f36f2a7510a0ff474554a1ae3ab134b639d1e97..46b128c08fef959a989826852a1d1c3bcb700124 100644 (file)
@@ -5,8 +5,10 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use Lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use Lib::TheTrait;
+   |
 
 error: aborting due to previous error
 
index edfe6348d174e5a741e163fdf7b05f5c06e65832..af0ef3b693262217f7581a2aaa07979df1e8bbbd 100644 (file)
@@ -5,8 +5,10 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use coherence_inherent_cc_lib::TheTrait;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use coherence_inherent_cc_lib::TheTrait;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/issue-85026.rs b/src/test/ui/coherence/issue-85026.rs
new file mode 100644 (file)
index 0000000..8b11654
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(auto_traits)]
+auto trait AutoTrait {}
+
+// You cannot impl your own `dyn AutoTrait`.
+impl dyn AutoTrait {} //~ERROR E0785
+
+// You cannot impl someone else's `dyn AutoTrait`
+impl dyn Unpin {} //~ERROR E0785
+
+fn main() {}
diff --git a/src/test/ui/coherence/issue-85026.stderr b/src/test/ui/coherence/issue-85026.stderr
new file mode 100644 (file)
index 0000000..a5da19b
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0785]: cannot define inherent `impl` for a dyn auto trait
+  --> $DIR/issue-85026.rs:5:6
+   |
+LL | impl dyn AutoTrait {}
+   |      ^^^^^^^^^^^^^ impl requires at least one non-auto trait
+   |
+   = note: define and implement a new trait or type instead
+
+error[E0785]: cannot define inherent `impl` for a dyn auto trait
+  --> $DIR/issue-85026.rs:8:6
+   |
+LL | impl dyn Unpin {}
+   |      ^^^^^^^^^ impl requires at least one non-auto trait
+   |
+   = note: define and implement a new trait or type instead
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0785`.
index 3bc62141927ae14358312ae03de46b01851b6202..2a04dc313e9b2e56c96936fa29e612b02cf9e584 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait Trait {}
 
index e533d4f7fb834e322d9f96c93ae7dde5e2e7549a..9762748f441f61c50ccc9d7a60155a5ee5d0823b 100644 (file)
@@ -1,11 +1,11 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/argument_order.rs:11:32
+  --> $DIR/argument_order.rs:10:32
    |
 LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
    |               -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b, const N: usize, T, const M: usize, U>`
 
 error[E0747]: lifetime provided when a type was expected
-  --> $DIR/argument_order.rs:19:23
+  --> $DIR/argument_order.rs:18:23
    |
 LL |     let _: AlsoBad<7, 'static, u32, 'static, 17, u16>;
    |                       ^^^^^^^
index f23bc6d6a2bfac79e242c405838ad92d55bfb26e..afd9ed1a7235dbe956c06f227801c52a1a3e8f05 100644 (file)
@@ -1,23 +1,23 @@
 error: type parameters must be declared prior to const parameters
-  --> $DIR/argument_order.rs:5:28
+  --> $DIR/argument_order.rs:4:28
    |
 LL | struct Bad<const N: usize, T> {
    |           -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
 
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/argument_order.rs:11:32
+  --> $DIR/argument_order.rs:10:32
    |
 LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
    |               -----------------^^-----^^-------------------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>`
 
 error: type parameters must be declared prior to const parameters
-  --> $DIR/argument_order.rs:11:36
+  --> $DIR/argument_order.rs:10:36
    |
 LL | struct AlsoBad<const N: usize, 'a, T, 'b, const M: usize, U> {
    |               ---------------------^----------------------^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b, T, U, const N: usize, const M: usize>`
 
 error[E0747]: lifetime provided when a type was expected
-  --> $DIR/argument_order.rs:19:23
+  --> $DIR/argument_order.rs:18:23
    |
 LL |     let _: AlsoBad<7, 'static, u32, 'static, 17, u16>;
    |                       ^^^^^^^
index 95eaeea58184017b32002169817e37d6847c3d13..97dd0f1435227c5cb58543e43891a66d072a8460 100644 (file)
@@ -1,6 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics_defaults))]
 
 struct Bad<const N: usize, T> {
     //[min]~^ ERROR type parameters must be declared prior to const parameters
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.full.stderr
deleted file mode 100644 (file)
index 0fb23e4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/array-size-in-generic-struct-param.rs:8:38
-   |
-LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-   |                                      ^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/array-size-in-generic-struct-param.rs:19:10
-   |
-LL |     arr: [u8; CFG.arr_size],
-   |          ^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
deleted file mode 100644 (file)
index 8f6e568..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/array-size-in-generic-struct-param.rs:8:48
-   |
-LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-   |                                                ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/array-size-in-generic-struct-param.rs:19:15
-   |
-LL |     arr: [u8; CFG.arr_size],
-   |               ^^^ cannot perform const operation using `CFG`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `CFG`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: `Config` is forbidden as the type of a const generic parameter
-  --> $DIR/array-size-in-generic-struct-param.rs:17:21
-   |
-LL | struct B<const CFG: Config> {
-   |                     ^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs
deleted file mode 100644 (file)
index cd0a974..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-#[allow(dead_code)]
-struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
-
-#[derive(PartialEq, Eq)]
-struct Config {
-    arr_size: usize,
-}
-
-struct B<const CFG: Config> {
-    //[min]~^ ERROR `Config` is forbidden
-    arr: [u8; CFG.arr_size],
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
-}
-
-const C: Config = Config { arr_size: 5 };
-
-fn main() {
-    let b = B::<C> { arr: [1, 2, 3, 4, 5] };
-    assert_eq!(b.arr.len(), 5);
-}
index 732a18714566ca68b450a9d86dce80059f0a3f4c..a712f691dbe2242cfbf64957f057bb379bff7870 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 #![allow(dead_code)]
 
diff --git a/src/test/ui/const-generics/associated-type-bound-fail.full.stderr b/src/test/ui/const-generics/associated-type-bound-fail.full.stderr
deleted file mode 100644 (file)
index 7ab430b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
-  --> $DIR/associated-type-bound-fail.rs:13:5
-   |
-LL |     type Assoc = u16;
-   |     ^^^^^^^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `u16`
-   |
-   = help: the following implementations were found:
-             <u16 as Bar<3_usize>>
-note: required by a bound in `Foo::Assoc`
-  --> $DIR/associated-type-bound-fail.rs:8:17
-   |
-LL |     type Assoc: Bar<N>;
-   |                 ^^^^^^ required by this bound in `Foo::Assoc`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/associated-type-bound-fail.min.stderr b/src/test/ui/const-generics/associated-type-bound-fail.min.stderr
deleted file mode 100644 (file)
index 7ab430b..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
-  --> $DIR/associated-type-bound-fail.rs:13:5
-   |
-LL |     type Assoc = u16;
-   |     ^^^^^^^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `u16`
-   |
-   = help: the following implementations were found:
-             <u16 as Bar<3_usize>>
-note: required by a bound in `Foo::Assoc`
-  --> $DIR/associated-type-bound-fail.rs:8:17
-   |
-LL |     type Assoc: Bar<N>;
-   |                 ^^^^^^ required by this bound in `Foo::Assoc`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index 83b267008057024a1ccb68024177a6cecffae933..937b8bcb6305785ca14706a7beae97dae48ad970 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
 trait Bar<const N: usize> {}
 
 trait Foo<const N: usize> {
diff --git a/src/test/ui/const-generics/associated-type-bound-fail.stderr b/src/test/ui/const-generics/associated-type-bound-fail.stderr
new file mode 100644 (file)
index 0000000..60e624f
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `u16: Bar<N>` is not satisfied
+  --> $DIR/associated-type-bound-fail.rs:9:5
+   |
+LL |     type Assoc = u16;
+   |     ^^^^^^^^^^^^^^^^^ the trait `Bar<N>` is not implemented for `u16`
+   |
+   = help: the following implementations were found:
+             <u16 as Bar<3_usize>>
+note: required by a bound in `Foo::Assoc`
+  --> $DIR/associated-type-bound-fail.rs:4:17
+   |
+LL |     type Assoc: Bar<N>;
+   |                 ^^^^^^ required by this bound in `Foo::Assoc`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 02f77396c0b6053797072977dff24ab5208c1782..3044736b47e05515122be179890921544e2e4eb8 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
 trait Bar<const N: usize> {}
 
 trait Foo<const N: usize> {
index 8d4cd9c0d6b7c9f40e5c6caa729fee5659590226..922f92d9feb71a44337bf4c5b948c1eaf44c77b1 100644 (file)
@@ -1,6 +1,3 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub struct Struct<const N: usize>(pub [u8; N]);
 
 pub type Alias = Struct<2>;
index d9baab956c9f3365222f34d11860a544b5c88f0a..19a8bb0f4eb21690b4958a6fe1b45aa797a0a684 100644 (file)
@@ -1,6 +1,4 @@
 // edition:2018
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 pub trait Foo<const N: usize> {}
 struct Local;
index 576276d902d60468f1d9c9a603d01f4ee2f2c117..5c2b1f4bddf82fa40f32668beaaac9c49d5a38ca 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // library portion of regression test for #87674
index 0d03f56854a77f7ee398af38702b5ac3b61fde45..cd5b8161d08ba997beec3b1d7b52d12bc089a82d 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // library portion of testing that `impl Trait<{ expr }>` doesnt
diff --git a/src/test/ui/const-generics/backcompat/trait-resolution-breakage.rs b/src/test/ui/const-generics/backcompat/trait-resolution-breakage.rs
new file mode 100644 (file)
index 0000000..df1c99e
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+trait Trait<T> {
+    const ASSOC_CONST: usize = 0;
+}
+
+impl Trait<()> for u8 {}
+
+// `u8::ASSOC_CONST` is resolved today, but will be ambiguous
+// under lazy normalization.
+fn foo<T, U>() -> [(T, U); u8::ASSOC_CONST]
+where
+    u8: Trait<T> + Trait<U>,
+{
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/backcompat/unevaluated-consts.rs b/src/test/ui/const-generics/backcompat/unevaluated-consts.rs
new file mode 100644 (file)
index 0000000..3f90d22
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+// If we allow the parent generics here without using lazy normalization
+// this results in a cycle error.
+struct Foo<T, U>(T, U);
+
+impl<T> From<[u8; 1 + 1]> for Foo<T, [u8; 1 + 1]> {
+    fn from(value: [u8; 1 + 1]) -> Foo<T, [u8; 1 + 1]> {
+        todo!();
+    }
+}
+
+fn break_me<T>()
+where
+    [u8; 1 + 1]: From<[u8; 1 + 1]>
+{}
+
+fn main() {}
index 34255fa9f58814cbd29c09d44b57232d816adfcb..6b6140e3a730cceb03ccb365b112fba2cbf47a7f 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub trait Foo {
     fn foo(&self);
 }
index ac358b01672bf807f24dcd2d354f4c043b93ac3a..f9e03151374a2190040f8d4d949c09436db6a90b 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 use std::fmt::Debug;
 
 #[derive(Debug)]
index 44aef859f2de64a8880a362e149d717ceea6f68a..a6e767489b79e3aeb8fbd1f6d046bba11ca0f0d7 100644 (file)
@@ -1,7 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 // This test confirms that the types can be inferred correctly for this example with const
 // generics. Previously this would ICE, and more recently error.
diff --git a/src/test/ui/const-generics/closing-args-token.full.stderr b/src/test/ui/const-generics/closing-args-token.full.stderr
deleted file mode 100644 (file)
index f4bb1e4..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/closing-args-token.rs:10:9
-   |
-LL |     S::<5 + 2 >> 7>;
-   |         ^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     S::<{ 5 + 2 } >> 7>;
-   |         +       +
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:10:16
-   |
-LL |     S::<5 + 2 >> 7>;
-   |                ^  ^
-   |
-help: split the comparison into two
-   |
-LL |     S::<5 + 2 >> 7 && 7>;
-   |                    ++++
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:16:20
-   |
-LL |     S::<{ 5 + 2 } >> 7>;
-   |                    ^  ^
-   |
-help: split the comparison into two
-   |
-LL |     S::<{ 5 + 2 } >> 7 && 7>;
-   |                        ++++
-
-error: expected expression, found `;`
-  --> $DIR/closing-args-token.rs:21:16
-   |
-LL |     T::<0 >= 3>;
-   |                ^ expected expression
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:27:12
-   |
-LL |     T::<x >>= 2 > 0>;
-   |            ^^   ^
-   |
-help: split the comparison into two
-   |
-LL |     T::<x >>= 2 && 2 > 0>;
-   |                 ++++
-
-error: aborting due to 5 previous errors
-
diff --git a/src/test/ui/const-generics/closing-args-token.min.stderr b/src/test/ui/const-generics/closing-args-token.min.stderr
deleted file mode 100644 (file)
index f4bb1e4..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/closing-args-token.rs:10:9
-   |
-LL |     S::<5 + 2 >> 7>;
-   |         ^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     S::<{ 5 + 2 } >> 7>;
-   |         +       +
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:10:16
-   |
-LL |     S::<5 + 2 >> 7>;
-   |                ^  ^
-   |
-help: split the comparison into two
-   |
-LL |     S::<5 + 2 >> 7 && 7>;
-   |                    ++++
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:16:20
-   |
-LL |     S::<{ 5 + 2 } >> 7>;
-   |                    ^  ^
-   |
-help: split the comparison into two
-   |
-LL |     S::<{ 5 + 2 } >> 7 && 7>;
-   |                        ++++
-
-error: expected expression, found `;`
-  --> $DIR/closing-args-token.rs:21:16
-   |
-LL |     T::<0 >= 3>;
-   |                ^ expected expression
-
-error: comparison operators cannot be chained
-  --> $DIR/closing-args-token.rs:27:12
-   |
-LL |     T::<x >>= 2 > 0>;
-   |            ^^   ^
-   |
-help: split the comparison into two
-   |
-LL |     T::<x >>= 2 && 2 > 0>;
-   |                 ++++
-
-error: aborting due to 5 previous errors
-
diff --git a/src/test/ui/const-generics/closing-args-token.rs b/src/test/ui/const-generics/closing-args-token.rs
deleted file mode 100644 (file)
index a9b552e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct S<const X: u32>;
-struct T<const X: bool>;
-
-fn bad_args_1() {
-    S::<5 + 2 >> 7>;
-    //~^ ERROR expressions must be enclosed in braces to be used as const generic arguments
-    //~| ERROR comparison operators cannot be chained
-}
-
-fn bad_args_2() {
-    S::<{ 5 + 2 } >> 7>;
-    //~^ ERROR comparison operators cannot be chained
-}
-
-fn bad_args_3() {
-    T::<0 >= 3>;
-    //~^ ERROR expected expression, found `;`
-}
-
-fn bad_args_4() {
-    let mut x = 0;
-    T::<x >>= 2 > 0>;
-    //~^ ERROR comparison operators cannot be chained
-}
-
-fn main() {}
index 8e20df2810399dabeeb0511abf333f99d79e01a9..ffd5eb9d462eda0efe3be7b4f7ca7fed693256cb 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn foo<const N: usize>(v: &[u8; N]) -> &[u8] {
     v
 }
index 8c31c8651a2b61e87c39c39716161da381b75656..372f0433e951150ac5b5d88bad3445cc73051c3e 100644 (file)
@@ -1,9 +1,5 @@
 // Test that a concrete const type i.e. A<2>, can be used as an argument type in a function
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: usize>; // ok
 
index 3d3bd2664c8b23c83e2f7c8254b9f89f9ec1cb4a..53c9c0ead0f9350809033bf0c438041031da259a 100644 (file)
@@ -1,10 +1,6 @@
 // Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>,
 // is callable.
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 pub struct A<const N: u32>;
 
index ad40b48afe5edef4721b23e524dbc1db1c2e1926..6f85237cf0aaf74410730d39e0a0433e235e9675 100644 (file)
@@ -2,7 +2,7 @@
 // run-pass
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 trait IsZeroTrait<const IS_ZERO: bool>{}
index d1bffae0d94cb7c145843c92c361f74912bbf819..aa0f9131aa7f5e42abc3a924ac28625136b094ea 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // This tests that the `conservative_is_privately_uninhabited` fn doesn't cause
index 96dbac1fbef4d0755e2d90701e87ed3e16c738d4..d0864414cc1fd3cbff46e4591fad9a4b823bd631 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // This tests that the `conservative_is_privately_uninhabited` fn doesn't cause
index bfa4ba3068628eecbd95771c88da9f7424e66c57..ac693426fbd983d6d295f4663e9f6ad890450938 100644 (file)
@@ -5,7 +5,7 @@ LL |     let _: [u8; foo::<T>()];
    |                       ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:14:23
@@ -14,7 +14,7 @@ LL |     let _: [u8; bar::<N>()];
    |                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:24:23
@@ -23,7 +23,7 @@ LL |     let _ = [0; bar::<N>()];
    |                       ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:29:24
@@ -32,7 +32,7 @@ LL |     let _: Foo<{ foo::<T>() }>;
    |                        ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:30:24
@@ -41,7 +41,7 @@ LL |     let _: Foo<{ bar::<N>() }>;
    |                        ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:35:27
@@ -50,7 +50,7 @@ LL |     let _ = Foo::<{ foo::<T>() }>;
    |                           ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/const-arg-in-const-arg.rs:36:27
@@ -59,7 +59,7 @@ LL |     let _ = Foo::<{ bar::<N>() }>;
    |                           ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:15:23
@@ -67,8 +67,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: [u8; faz::<'a>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:16:23
@@ -76,8 +76,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: [u8; baz::<'a>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:17:23
@@ -85,8 +85,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: [u8; faz::<'b>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:18:23
@@ -94,8 +94,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: [u8; baz::<'b>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:25:23
@@ -103,8 +103,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = [0; faz::<'a>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:26:23
@@ -112,8 +112,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = [0; baz::<'a>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:27:23
@@ -121,8 +121,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = [0; faz::<'b>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:28:23
@@ -130,8 +130,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = [0; baz::<'b>(&())];
    |                       ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:31:24
@@ -139,8 +139,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: Foo<{ faz::<'a>(&()) }>;
    |                        ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:32:24
@@ -148,8 +148,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: Foo<{ baz::<'a>(&()) }>;
    |                        ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:33:24
@@ -157,8 +157,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: Foo<{ faz::<'b>(&()) }>;
    |                        ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:34:24
@@ -166,8 +166,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _: Foo<{ baz::<'b>(&()) }>;
    |                        ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:37:27
@@ -175,8 +175,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = Foo::<{ faz::<'a>(&()) }>;
    |                           ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:38:27
@@ -184,8 +184,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = Foo::<{ baz::<'a>(&()) }>;
    |                           ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:39:27
@@ -193,8 +193,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = Foo::<{ faz::<'b>(&()) }>;
    |                           ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/const-arg-in-const-arg.rs:40:27
@@ -202,8 +202,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     let _ = Foo::<{ baz::<'b>(&()) }>;
    |                           ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error: aborting due to 23 previous errors
 
index 8279f4a3f61ea85743fb19ffa0c3fa1f483555c0..39f0b23733029b580728ba1d80db2cb89fdc51a5 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: min
-// FIXME(const_generics): This test currently causes an ICE because
+// FIXME(generic_const_exprs): This test currently causes an ICE because
 // we don't yet correctly deal with lifetimes, reenable this test once
 // this is fixed.
 
index 43ed12efb895a101f56b0337a0a18449ebeb1d86..9b225b18d73031b7b099700151685eb15520e692 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn const_u32_identity<const X: u32>() -> u32 {
     X
 }
diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.full.stderr
deleted file mode 100644 (file)
index d0ea51e..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0747]: constant provided when a type was expected
-  --> $DIR/const-arg-type-arg-misordered.rs:7:35
-   |
-LL | fn foo<const N: usize>() -> Array<N, ()> {
-   |                                   ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.min.stderr
deleted file mode 100644 (file)
index d7b7df0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0747]: constant provided when a type was expected
-  --> $DIR/const-arg-type-arg-misordered.rs:7:35
-   |
-LL | fn foo<const N: usize>() -> Array<N, ()> {
-   |                                   ^
-   |
-   = note: type arguments must be provided before constant arguments
-   = help: reorder the arguments: types, then consts: `<T, N>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0747`.
index 5415791d21bb3b87b735a0604e8226bdea77211c..8ee17e637aa3028f994a0145d7abe2d7636c4b85 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 type Array<T, const N: usize> = [T; N];
 
 fn foo<const N: usize>() -> Array<N, ()> {
diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr
new file mode 100644 (file)
index 0000000..104ee9b
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0747]: constant provided when a type was expected
+  --> $DIR/const-arg-type-arg-misordered.rs:3:35
+   |
+LL | fn foo<const N: usize>() -> Array<N, ()> {
+   |                                   ^
+   |
+   = note: type arguments must be provided before constant arguments
+   = help: reorder the arguments: types, then consts: `<T, N>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.full.stderr
deleted file mode 100644 (file)
index 6ef698b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/const-argument-cross-crate-mismatch.rs:9:67
-   |
-LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
-   |                                                                   ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
-
-error[E0308]: mismatched types
-  --> $DIR/const-argument-cross-crate-mismatch.rs:11:65
-   |
-LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
-   |                                                                 ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.min.stderr
deleted file mode 100644 (file)
index 6ef698b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/const-argument-cross-crate-mismatch.rs:9:67
-   |
-LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
-   |                                                                   ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
-
-error[E0308]: mismatched types
-  --> $DIR/const-argument-cross-crate-mismatch.rs:11:65
-   |
-LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
-   |                                                                 ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index a8f533eceaa6d98f9cf1fe8ced240d833d008ef8..d863d097d5caf324554f323cf7f3bb0953205027 100644 (file)
@@ -1,7 +1,4 @@
 // aux-build:const_generic_lib.rs
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 extern crate const_generic_lib;
 
diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr
new file mode 100644 (file)
index 0000000..aefd514
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/const-argument-cross-crate-mismatch.rs:6:67
+   |
+LL |     let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8]));
+   |                                                                   ^^^^^^^^^^ expected an array with a fixed size of 3 elements, found one with 2 elements
+
+error[E0308]: mismatched types
+  --> $DIR/const-argument-cross-crate-mismatch.rs:8:65
+   |
+LL |     let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]);
+   |                                                                 ^^^^^^^^^^^^^^^ expected an array with a fixed size of 2 elements, found one with 3 elements
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 8e62147eb7e30c25fa11ae5f9d9196319f4e0801..8c5c3b17b5c474044278f8fbb83cb49ca28fb621 100644 (file)
@@ -1,24 +1,5 @@
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/const-argument-if-length.rs:7:28
-   |
-LL | pub const fn is_zst<T: ?Sized>() -> usize {
-   |                     - this type parameter needs to be `std::marker::Sized`
-LL |     if std::mem::size_of::<T>() == 0 {
-   |                            ^ doesn't have a size known at compile-time
-   |
-note: required by a bound in `std::mem::size_of`
-  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL | pub const fn size_of<T>() -> usize {
-   |                      ^ required by this bound in `std::mem::size_of`
-help: consider removing the `?Sized` bound to make the type parameter `Sized`
-   |
-LL - pub const fn is_zst<T: ?Sized>() -> usize {
-LL + pub const fn is_zst<T>() -> usize {
-   | 
-
-error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/const-argument-if-length.rs:16:12
+  --> $DIR/const-argument-if-length.rs:15:12
    |
 LL | pub struct AtLeastByte<T: ?Sized> {
    |                        - this type parameter needs to be `std::marker::Sized`
@@ -41,6 +22,14 @@ help: the `Box` type always has a statically known size and allocates its conten
 LL |     value: Box<T>,
    |            ++++ +
 
+error: unconstrained generic constant
+  --> $DIR/const-argument-if-length.rs:17:10
+   |
+LL |     pad: [u8; is_zst::<T>()],
+   |          ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index cdbbbf2a99b3bf2c3ea104be5a13bb0fc932c29d..b123036bf25060f2b303859d5fe6d46132c40b52 100644 (file)
@@ -1,14 +1,14 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/const-argument-if-length.rs:18:24
+  --> $DIR/const-argument-if-length.rs:17:24
    |
 LL |     pad: [u8; is_zst::<T>()],
    |                        ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/const-argument-if-length.rs:16:12
+  --> $DIR/const-argument-if-length.rs:15:12
    |
 LL | pub struct AtLeastByte<T: ?Sized> {
    |                        - this type parameter needs to be `std::marker::Sized`
index 67ed85f96afd7f2ddf55e6fece652fdcb60526d6..db1eafca2c7222186503d3276dd4cfe73f7bf1d7 100644 (file)
@@ -1,11 +1,10 @@
 // revisions: full min
 
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
 
 pub const fn is_zst<T: ?Sized>() -> usize {
     if std::mem::size_of::<T>() == 0 {
-        //[full]~^ ERROR the size for values of type `T` cannot be known at compilation time
         1
     } else {
         0
@@ -17,6 +16,7 @@ pub struct AtLeastByte<T: ?Sized> {
     //~^ ERROR the size for values of type `T` cannot be known at compilation time
     pad: [u8; is_zst::<T>()],
     //[min]~^ ERROR generic parameters may not be used in const operations
+    //[full]~^^ ERROR unconstrained generic constant
 }
 
 fn main() {}
index dc34621b90500f16365402a274cc6cf04a09e924..2aca7bdeb9a1442e172a08eda5d07585b5c182bf 100644 (file)
@@ -2,7 +2,7 @@
 // revisions: full
 // FIXME(#75323) Omitted min revision for now due to ICE.
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 #![allow(dead_code)]
 
diff --git a/src/test/ui/const-generics/const-expression-parameter.full.stderr b/src/test/ui/const-generics/const-expression-parameter.full.stderr
deleted file mode 100644 (file)
index 4ce0ecd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/const-expression-parameter.rs:15:20
-   |
-LL |     i32_identity::<1 + 2>();
-   |                    ^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     i32_identity::<{ 1 + 2 }>();
-   |                    +       +
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const-expression-parameter.min.stderr b/src/test/ui/const-generics/const-expression-parameter.min.stderr
deleted file mode 100644 (file)
index 4ce0ecd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/const-expression-parameter.rs:15:20
-   |
-LL |     i32_identity::<1 + 2>();
-   |                    ^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     i32_identity::<{ 1 + 2 }>();
-   |                    +       +
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs
deleted file mode 100644 (file)
index cb609a5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-fn i32_identity<const X: i32>() -> i32 {
-    5
-}
-
-fn foo_a() {
-    i32_identity::<-1>(); // ok
-}
-
-fn foo_b() {
-    i32_identity::<1 + 2>(); //~ ERROR expressions must be enclosed in braces
-}
-
-fn foo_c() {
-    i32_identity::< -1 >(); // ok
-}
-
-fn main() {
-    i32_identity::<5>(); // ok
-}
index 5c1ee4e0d5a9eebbfe60df610111e630d2b41b29..161bfaab48aded5312667e89da11f1c9fe9e729b 100644 (file)
@@ -1,9 +1,5 @@
 // Checks that `const fn` with const params can be used.
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 const fn const_u32_identity<const X: u32>() -> u32 {
     X
diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.rs b/src/test/ui/const-generics/const-generic-array-wrapper.rs
deleted file mode 100644 (file)
index 224fc79..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct Foo<T, const N: usize>([T; N]);
-
-impl<T, const N: usize> Foo<T, N> {
-    fn foo(&self) -> usize {
-        N
-    }
-}
-
-fn main() {
-    let foo = Foo([0u32; 21]);
-    assert_eq!(foo.0, [0u32; 21]);
-    assert_eq!(foo.foo(), 21);
-}
index 95632f798969f96827fee0ffe756c3172352a9c8..bb16be9c58c3ff99b5b3035d06fe3ffd517be441 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 #[derive(Debug)]
 struct S<const N: usize>;
index 6c2b14f2770da147c56c556222b70e88a9dc8eaa..d8a0e076e0a46ac464e91570a93a29202e0667c8 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<const A: usize, const B: usize>;
 
index 09a4f66de39c52348c32cdae49cf01f58d7deccd..982417eb3c61e7d65bed83da0e8af5ef8afd2915 100644 (file)
@@ -1,8 +1,8 @@
 error: lifetime parameters must be declared prior to const parameters
   --> $DIR/const-param-before-other-params.rs:5:21
    |
-LL | fn bar<const X: (), 'a>(_: &'a ()) {
-   |       --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: ()>`
+LL | fn bar<const X: u8, 'a>(_: &'a ()) {
+   |       --------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const X: u8>`
 
 error: aborting due to previous error
 
index a9349ce43c94e7f2456f348c17c346f7e85206ed..f439cd9d69fcce59abc7d74fe362a65f87f269c6 100644 (file)
@@ -1,32 +1,14 @@
 error: lifetime parameters must be declared prior to const parameters
   --> $DIR/const-param-before-other-params.rs:5:21
    |
-LL | fn bar<const X: (), 'a>(_: &'a ()) {
-   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>`
+LL | fn bar<const X: u8, 'a>(_: &'a ()) {
+   |       --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: u8>`
 
 error: type parameters must be declared prior to const parameters
-  --> $DIR/const-param-before-other-params.rs:10:21
+  --> $DIR/const-param-before-other-params.rs:9:21
    |
-LL | fn foo<const X: (), T>(_: &T) {}
-   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: ()>`
+LL | fn foo<const X: u8, T>(_: &T) {}
+   |       --------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const X: u8>`
 
-error: `()` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-before-other-params.rs:5:17
-   |
-LL | fn bar<const X: (), 'a>(_: &'a ()) {
-   |                 ^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: `()` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-before-other-params.rs:10:17
-   |
-LL | fn foo<const X: (), T>(_: &T) {}
-   |                 ^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
index 508bb3e6a689ecc28ab5ecb8cce3eec34e13a695..0a7b57fe626b1b0212adc96a62c511032f7b17b0 100644 (file)
@@ -1,14 +1,12 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(const_generics_defaults))]
 #![cfg_attr(full, allow(incomplete_features))]
 
-fn bar<const X: (), 'a>(_: &'a ()) {
+fn bar<const X: u8, 'a>(_: &'a ()) {
     //~^ ERROR lifetime parameters must be declared prior to const parameters
-    //[min]~^^ ERROR `()` is forbidden as the type of a const generic parameter
 }
 
-fn foo<const X: (), T>(_: &T) {}
+fn foo<const X: u8, T>(_: &T) {}
 //[min]~^ ERROR type parameters must be declared prior to const parameters
-//[min]~^^ ERROR `()` is forbidden as the type of a const generic parameter
 
 fn main() {}
index 119f932745b3f05670e4c2da7d6d9f9794b8e0ee..d6753a74f857482cb613c0b96d399ba1751f00df 100644 (file)
@@ -1,29 +1,29 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:10:19
+  --> $DIR/const-param-elided-lifetime.rs:9:19
    |
 LL | struct A<const N: &u8>;
    |                   ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:15:15
+  --> $DIR/const-param-elided-lifetime.rs:14:15
    |
 LL | impl<const N: &u8> A<N> {
    |               ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:18:21
+  --> $DIR/const-param-elided-lifetime.rs:17:21
    |
 LL |     fn foo<const M: &u8>(&self) {}
    |                     ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:23:15
+  --> $DIR/const-param-elided-lifetime.rs:22:15
    |
 LL | impl<const N: &u8> B for A<N> {}
    |               ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:27:17
+  --> $DIR/const-param-elided-lifetime.rs:26:17
    |
 LL | fn bar<const N: &u8>() {}
    |                 ^ explicit lifetime name needed here
index 613918f78f36c84364310452a6847dbf15d1756c..48d85e7ff64ecfc17f6c09fa506fc3fd7c130d77 100644 (file)
@@ -1,77 +1,77 @@
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:10:19
+  --> $DIR/const-param-elided-lifetime.rs:9:19
    |
 LL | struct A<const N: &u8>;
    |                   ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:15:15
+  --> $DIR/const-param-elided-lifetime.rs:14:15
    |
 LL | impl<const N: &u8> A<N> {
    |               ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:18:21
+  --> $DIR/const-param-elided-lifetime.rs:17:21
    |
 LL |     fn foo<const M: &u8>(&self) {}
    |                     ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:23:15
+  --> $DIR/const-param-elided-lifetime.rs:22:15
    |
 LL | impl<const N: &u8> B for A<N> {}
    |               ^ explicit lifetime name needed here
 
 error[E0637]: `&` without an explicit lifetime name cannot be used here
-  --> $DIR/const-param-elided-lifetime.rs:27:17
+  --> $DIR/const-param-elided-lifetime.rs:26:17
    |
 LL | fn bar<const N: &u8>() {}
    |                 ^ explicit lifetime name needed here
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:10:19
+  --> $DIR/const-param-elided-lifetime.rs:9:19
    |
 LL | struct A<const N: &u8>;
    |                   ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:15:15
+  --> $DIR/const-param-elided-lifetime.rs:14:15
    |
 LL | impl<const N: &u8> A<N> {
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:18:21
+  --> $DIR/const-param-elided-lifetime.rs:17:21
    |
 LL |     fn foo<const M: &u8>(&self) {}
    |                     ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:23:15
+  --> $DIR/const-param-elided-lifetime.rs:22:15
    |
 LL | impl<const N: &u8> B for A<N> {}
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
-  --> $DIR/const-param-elided-lifetime.rs:27:17
+  --> $DIR/const-param-elided-lifetime.rs:26:17
    |
 LL | fn bar<const N: &u8>() {}
    |                 ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 10 previous errors
 
index 89715a7b8e9d4557066577979d8b9fd10f95a876..487b82dbf4ac4d9529358c3a5f9c4e28f1033c74 100644 (file)
@@ -3,8 +3,7 @@
 // elided lifetimes within the type of a const generic parameters to be 'static, like elided
 // lifetimes within const/static items.
 // revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: &u8>;
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.full.stderr
deleted file mode 100644 (file)
index c2ec735..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/const-param-from-outer-fn.rs:8:9
-   |
-LL | fn foo<const X: u32>() {
-   |              - const parameter from outer function
-LL |     fn bar() -> u32 {
-   |        --- try adding a local generic parameter in this method instead
-LL |         X
-   |         ^ use of generic parameter from outer function
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.min.stderr
deleted file mode 100644 (file)
index c2ec735..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/const-param-from-outer-fn.rs:8:9
-   |
-LL | fn foo<const X: u32>() {
-   |              - const parameter from outer function
-LL |     fn bar() -> u32 {
-   |        --- try adding a local generic parameter in this method instead
-LL |         X
-   |         ^ use of generic parameter from outer function
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.rs b/src/test/ui/const-generics/const-param-from-outer-fn.rs
deleted file mode 100644 (file)
index 27b9ca9..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-fn foo<const X: u32>() {
-    fn bar() -> u32 {
-        X //~ ERROR can't use generic parameters from outer function
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const-param-hygiene.rs b/src/test/ui/const-generics/const-param-hygiene.rs
deleted file mode 100644 (file)
index 9cafb05..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-macro_rules! bar {
-    ($($t:tt)*) => { impl<const N: usize> $($t)* };
-}
-
-macro_rules! baz {
-    ($t:tt) => { fn test<const M: usize>(&self) -> usize { $t } };
-}
-
-struct Foo<const N: usize>;
-
-bar!(Foo<N> { baz!{ M } });
-
-fn main() {
-    assert_eq!(Foo::<7>.test::<3>(), 3);
-}
index 9dc9c80241d5922a023287011f58953518563d1f..f823431e69b9ef51e3148cc949daf3ed28aa936c 100644 (file)
@@ -1,8 +1,5 @@
 // edition:2018
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 async fn foo<const N: usize>(arg: [u8; N]) -> usize { arg.len() }
 
diff --git a/src/test/ui/const-generics/const-param-in-trait.rs b/src/test/ui/const-generics/const-param-in-trait.rs
deleted file mode 100644 (file)
index 79b3ae2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Check that const parameters are permitted in traits.
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-
-trait Trait<const T: u8> {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const-param-shadowing.rs b/src/test/ui/const-generics/const-param-shadowing.rs
deleted file mode 100644 (file)
index ddd15db..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-type N = u32;
-struct Foo<const M: usize>;
-fn test<const N: usize>() -> Foo<N> { //~ ERROR type provided when
-    Foo
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const-param-shadowing.stderr b/src/test/ui/const-generics/const-param-shadowing.stderr
deleted file mode 100644 (file)
index 625338b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0747]: type provided when a constant was expected
-  --> $DIR/const-param-shadowing.rs:3:34
-   |
-LL | fn test<const N: usize>() -> Foo<N> {
-   |                                  ^
-   |
-help: if this generic argument was intended as a const parameter, surround it with braces
-   |
-LL | fn test<const N: usize>() -> Foo<{ N }> {
-   |                                  +   +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0747`.
index 9804363f39a948c3c420d738c395044d7f735bb2..a7b78b80ca5ea4a1082437d88f9daf797a62270e 100644 (file)
@@ -17,7 +17,7 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
    |                                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-type-depends-on-const-param.rs:15:35
@@ -26,7 +26,7 @@ LL | pub struct SelfDependent<const N: [u8; N]>;
    |                                   ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 4 previous errors
 
index 62b146e016a13c7bc8e9dba21d6bce867d50bbbf..9d50f9a47ff6ef46d8e40ed363677db70f20f7ab 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 // Currently, const parameters cannot depend on other generic parameters,
index 910a964350226555065b2202e5dc04f7786ba293..71d91fd7e7f453cc3feda587a899c2b87452ab1e 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 // Currently, const parameters cannot depend on other generic parameters,
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.full.stderr
deleted file mode 100644 (file)
index 923964a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: const parameter `x` should have an upper case name
-  --> $DIR/const-parameter-uppercase-lint.rs:8:15
-   |
-LL | fn noop<const x: u32>() {
-   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
-   |
-note: the lint level is defined here
-  --> $DIR/const-parameter-uppercase-lint.rs:6:9
-   |
-LL | #![deny(non_upper_case_globals)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.min.stderr
deleted file mode 100644 (file)
index 923964a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: const parameter `x` should have an upper case name
-  --> $DIR/const-parameter-uppercase-lint.rs:8:15
-   |
-LL | fn noop<const x: u32>() {
-   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
-   |
-note: the lint level is defined here
-  --> $DIR/const-parameter-uppercase-lint.rs:6:9
-   |
-LL | #![deny(non_upper_case_globals)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index 5d97907c2e7fa430fcc7852e82dabc769d1cc1e7..b08d62ccc7b1642b9b5a4550cb8b32ff1f755e36 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 #![deny(non_upper_case_globals)]
 
 fn noop<const x: u32>() {
diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr
new file mode 100644 (file)
index 0000000..efaa182
--- /dev/null
@@ -0,0 +1,14 @@
+error: const parameter `x` should have an upper case name
+  --> $DIR/const-parameter-uppercase-lint.rs:3:15
+   |
+LL | fn noop<const x: u32>() {
+   |               ^ help: convert the identifier to upper case (notice the capitalization): `X`
+   |
+note: the lint level is defined here
+  --> $DIR/const-parameter-uppercase-lint.rs:1:9
+   |
+LL | #![deny(non_upper_case_globals)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/const-types.rs b/src/test/ui/const-generics/const-types.rs
deleted file mode 100644 (file)
index fb150f8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Check that arrays can be used with generic const and type.
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-#![allow(dead_code, unused_variables)]
-
-struct ConstArray<T, const LEN: usize> {
-    array: [T; LEN],
-}
-
-fn main() {
-    let arr = ConstArray::<i32, 8> {
-        array: [0; 8],
-    };
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-1.rs
deleted file mode 100644 (file)
index 744a1c4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-#![feature(const_evaluatable_checked, const_generics)]
-#![allow(incomplete_features)]
-
-struct Foo<const N: u8>([u8; N as usize])
-where
-    [(); N as usize]:;
-
-struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:;
-
-// unifying with subtrees
-struct Evaluatable<const N: u16>;
-fn foo<const N: u8>() where Evaluatable<{N as usize as u16 }>: {
-    let _ = Foo::<N>([1; N as usize]);
-}
-
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.rs
deleted file mode 100644 (file)
index 5437746..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#![feature(const_evaluatable_checked, const_generics)]
-#![allow(incomplete_features)]
-
-struct Evaluatable<const N: u128> {}
-
-struct Foo<const N: u8>([u8; N as usize])
-//~^ Error: unconstrained generic constant
-//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
-where
-    Evaluatable<{N as u128}>:;
-
-struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
-//~^ Error: unconstrained generic constant
-//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
-
-struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
-//~^ Error: unconstrained generic constant
-//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-2.stderr
deleted file mode 100644 (file)
index 5ca04d2..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-2.rs:6:25
-   |
-LL | struct Foo<const N: u8>([u8; N as usize])
-   |                         ^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); N as usize]:`
-
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-2.rs:12:26
-   |
-LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
-
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-2.rs:16:25
-   |
-LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.rs
deleted file mode 100644 (file)
index 2ca06bd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait Trait {}
-pub struct EvaluatableU128<const N: u128>;
-
-struct HasCastInTraitImpl<const N: usize, const M: u128>;
-impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-
-pub fn use_trait_impl<const N: usize>()
-where
-    [(); { N + 1}]:,
-    EvaluatableU128<{N as u128}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    // errors are bad but seems to be pre-existing issue #86198
-    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-    //~^ Error: mismatched types
-    //~^^ Error: unconstrained generic constant
-    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-    //~^ Error: mismatched types
-    //~^^ Error: unconstrained generic constant
-    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
-    //~^ Error: mismatched types
-    assert_impl::<HasCastInTraitImpl<14, 13>>();
-    //~^ Error: mismatched types
-}
-pub fn use_trait_impl_2<const N: usize>()
-where
-    [(); { N + 1}]:,
-    EvaluatableU128<{N as _}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    // errors are bad but seems to be pre-existing issue #86198
-    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-    //~^ Error: mismatched types
-    //~^^ Error: unconstrained generic constant
-    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-    //~^ Error: mismatched types
-    //~^^ Error: unconstrained generic constant
-    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
-    //~^ Error: mismatched types
-    assert_impl::<HasCastInTraitImpl<14, 13>>();
-    //~^ Error: mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-3.stderr
deleted file mode 100644 (file)
index f235eb4..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:17:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
-  --> $DIR/abstract-const-as-cast-3.rs:8:22
-   |
-LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `use_trait_impl::assert_impl`
-  --> $DIR/abstract-const-as-cast-3.rs:14:23
-   |
-LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:17:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
-   |
-   = note: expected type `{ N as u128 }`
-              found type `{ O as u128 }`
-
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:20:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
-  --> $DIR/abstract-const-as-cast-3.rs:8:22
-   |
-LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `use_trait_impl::assert_impl`
-  --> $DIR/abstract-const-as-cast-3.rs:14:23
-   |
-LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:20:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
-   |
-   = note: expected type `{ N as _ }`
-              found type `{ O as u128 }`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:23:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
-   |
-   = note: expected type `12_u128`
-              found type `13_u128`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:25:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
-   |
-   = note: expected type `13_u128`
-              found type `14_u128`
-
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:35:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
-  --> $DIR/abstract-const-as-cast-3.rs:8:22
-   |
-LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `use_trait_impl_2::assert_impl`
-  --> $DIR/abstract-const-as-cast-3.rs:32:23
-   |
-LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:35:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
-   |
-   = note: expected type `{ N as u128 }`
-              found type `{ O as u128 }`
-
-error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:38:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
-  --> $DIR/abstract-const-as-cast-3.rs:8:22
-   |
-LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `use_trait_impl_2::assert_impl`
-  --> $DIR/abstract-const-as-cast-3.rs:32:23
-   |
-LL |     fn assert_impl<T: Trait>() {}
-   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:38:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
-   |
-   = note: expected type `{ N as _ }`
-              found type `{ O as u128 }`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:41:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
-   |
-   = note: expected type `12_u128`
-              found type `13_u128`
-
-error[E0308]: mismatched types
-  --> $DIR/abstract-const-as-cast-3.rs:43:5
-   |
-LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
-   |
-   = note: expected type `13_u128`
-              found type `14_u128`
-
-error: aborting due to 12 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs b/src/test/ui/const-generics/const_evaluatable_checked/abstract-const-as-cast-4.rs
deleted file mode 100644 (file)
index 0bb4fcf..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// check-pass
-#![feature(const_evaluatable_checked, const_generics)]
-#![allow(incomplete_features)]
-
-trait Trait {}
-pub struct EvaluatableU128<const N: u128>;
-
-struct HasCastInTraitImpl<const N: usize, const M: u128>;
-impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
-
-pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
-    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<13, 13>>();
-}
-pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, {
-    fn assert_impl<T: Trait>() {}
-
-    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
-    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
-    assert_impl::<HasCastInTraitImpl<13, 13>>();
-}
-
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs b/src/test/ui/const-generics/const_evaluatable_checked/associated-consts.rs
deleted file mode 100644 (file)
index 533fe55..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-pub trait BlockCipher {
-    const BLOCK_SIZE: usize;
-}
-
-struct FooCipher;
-impl BlockCipher for FooCipher {
-    const BLOCK_SIZE: usize = 64;
-}
-
-struct BarCipher;
-impl BlockCipher for BarCipher {
-    const BLOCK_SIZE: usize = 32;
-}
-
-pub struct Block<C>(C);
-
-pub fn test<C: BlockCipher, const M: usize>()
-where
-    [u8; M - C::BLOCK_SIZE]: Sized,
-{
-    let _ = [0; M - C::BLOCK_SIZE];
-}
-
-fn main() {
-    test::<FooCipher, 128>();
-    test::<BarCipher, 64>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs b/src/test/ui/const-generics/const_evaluatable_checked/auxiliary/const_evaluatable_lib.rs
deleted file mode 100644 (file)
index 9745dfe..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
-where
-    [u8; std::mem::size_of::<T>() - 1]: Sized,
-{
-    [0; std::mem::size_of::<T>() - 1]
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/closures.rs b/src/test/ui/const-generics/const_evaluatable_checked/closures.rs
deleted file mode 100644 (file)
index 32f4359..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
-//~^ ERROR overly complex generic constant
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr b/src/test/ui/const-generics/const_evaluatable_checked/closures.stderr
deleted file mode 100644 (file)
index 9f0b725..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error: overly complex generic constant
-  --> $DIR/closures.rs:3:35
-   |
-LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
-   |                                   ^^^^-------^^
-   |                                       |
-   |                                       unsupported rvalue
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate.rs
deleted file mode 100644 (file)
index 53b2378..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// aux-build:const_evaluatable_lib.rs
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-extern crate const_evaluatable_lib;
-
-fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized {
-    assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]);
-}
-
-fn main() {
-    assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]);
-    user::<u32>();
-    user::<u64>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
deleted file mode 100644 (file)
index e3a4d9a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// aux-build:const_evaluatable_lib.rs
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-extern crate const_evaluatable_lib;
-
-fn user<T>() {
-    let _ = const_evaluatable_lib::test1::<T>();
-    //~^ ERROR unconstrained generic constant
-    //~| ERROR unconstrained generic constant
-    //~| ERROR unconstrained generic constant
-    //~| ERROR unconstrained generic constant
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
deleted file mode 100644 (file)
index 7b4d46b..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/cross_crate_predicate.rs:7:13
-   |
-LL |     let _ = const_evaluatable_lib::test1::<T>();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
-note: required by a bound in `test1`
-  --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
-   |
-LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
-
-error: unconstrained generic constant
-  --> $DIR/cross_crate_predicate.rs:7:13
-   |
-LL |     let _ = const_evaluatable_lib::test1::<T>();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
-note: required by a bound in `test1`
-  --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
-   |
-LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
-
-error: unconstrained generic constant
-  --> $DIR/cross_crate_predicate.rs:7:13
-   |
-LL |     let _ = const_evaluatable_lib::test1::<T>();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
-note: required by a bound in `test1`
-  --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
-   |
-LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
-
-error: unconstrained generic constant
-  --> $DIR/cross_crate_predicate.rs:7:13
-   |
-LL |     let _ = const_evaluatable_lib::test1::<T>();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
-note: required by a bound in `test1`
-  --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
-   |
-LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.rs
deleted file mode 100644 (file)
index 26c4295..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-use std::mem::size_of;
-use std::marker::PhantomData;
-
-struct Foo<T>(PhantomData<T>);
-
-fn test<T>() -> [u8; size_of::<T>()] {
-    [0; size_of::<Foo<T>>()]
-    //~^ ERROR unconstrained generic constant
-    //~| ERROR mismatched types
-}
-
-fn main() {
-    test::<u32>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr b/src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr
deleted file mode 100644 (file)
index 2aeb9b9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/different-fn.rs:10:5
-   |
-LL |     [0; size_of::<Foo<T>>()]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()`
-   |
-   = note: expected type `size_of::<T>()`
-              found type `size_of::<Foo<T>>()`
-
-error: unconstrained generic constant
-  --> $DIR/different-fn.rs:10:9
-   |
-LL |     [0; size_of::<Foo<T>>()]
-   |         ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/division.rs b/src/test/ui/const-generics/const_evaluatable_checked/division.rs
deleted file mode 100644 (file)
index 71a5f2d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn with_bound<const N: usize>() where [u8; N / 2]: Sized {
-    let _: [u8; N / 2] = [0; N / 2];
-}
-
-fn main() {
-    with_bound::<4>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs b/src/test/ui/const-generics/const_evaluatable_checked/dont-eagerly-error-in-is-const-evaluatable.rs
deleted file mode 100644 (file)
index 92a410a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-#![feature(const_generics)]
-#![feature(const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This test is a repro for #82279. It checks that we don't error
-// when calling is_const_evaluatable on `std::mem::size_of::<T>()`
-// when looking for candidates that may prove `T: Foo` in `foo`
-
-trait Foo {}
-
-#[allow(dead_code)]
-fn foo<T: Foo>() {}
-
-impl<T> Foo for T where [(); std::mem::size_of::<T>()]:  {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/drop_impl.rs b/src/test/ui/const-generics/const_evaluatable_checked/drop_impl.rs
deleted file mode 100644 (file)
index 41fb5d7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-//check-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-struct Foo<const N: usize>
-where
-    [(); N + 1]: ;
-
-impl<const N: usize> Drop for Foo<N>
-where
-    [(); N + 1]: ,
-{
-    fn drop(&mut self) {}
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs b/src/test/ui/const-generics/const_evaluatable_checked/elaborate-trait-pred.rs
deleted file mode 100644 (file)
index 4a4fd1e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-// Test that we use the elaborated predicates from traits
-// to satisfy const evaluatable predicates.
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-use std::mem::size_of;
-
-trait Foo: Sized
-where
-    [(); size_of::<Self>()]: Sized,
-{
-}
-
-impl Foo for u64 {}
-impl Foo for u32 {}
-
-fn foo<T: Foo>() -> [u8; size_of::<T>()] {
-    [0; size_of::<T>()]
-}
-
-fn main() {
-    assert_eq!(foo::<u32>(), [0; 4]);
-    assert_eq!(foo::<u64>(), [0; 8]);
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.rs
deleted file mode 100644 (file)
index 9f457fb..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#![crate_type = "lib"]
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-pub struct Const<const U: u8>;
-
-pub trait Trait {
-    type AssocTy;
-    fn assoc_fn() -> Self::AssocTy;
-}
-
-impl<const U: u8> Trait for Const<U>
-//~^ WARN private type
-//~| WARN this was previously
-//~| WARN private type
-//~| WARN this was previously
-
-where
-    Const<{ my_const_fn(U) }>: ,
-{
-    type AssocTy = Const<{ my_const_fn(U) }>;
-    //~^ ERROR private type
-    fn assoc_fn() -> Self::AssocTy {
-        Const
-    }
-}
-
-const fn my_const_fn(val: u8) -> u8 {
-    // body of this function doesn't matter
-    val
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr b/src/test/ui/const-generics/const_evaluatable_checked/eval-privacy.stderr
deleted file mode 100644 (file)
index 842c22c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
-  --> $DIR/eval-privacy.rs:12:1
-   |
-LL | / impl<const U: u8> Trait for Const<U>
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^
-   |
-   = note: `#[warn(private_in_public)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
-warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
-  --> $DIR/eval-privacy.rs:12:1
-   |
-LL | / impl<const U: u8> Trait for Const<U>
-LL | |
-LL | |
-LL | |
-...  |
-LL | |     }
-LL | | }
-   | |_^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
-
-error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
-  --> $DIR/eval-privacy.rs:21:5
-   |
-LL |     type AssocTy = Const<{ my_const_fn(U) }>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
-...
-LL | const fn my_const_fn(val: u8) -> u8 {
-   | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
-
-error: aborting due to previous error; 2 warnings emitted
-
-For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/evaluated-to-ambig.rs b/src/test/ui/const-generics/const_evaluatable_checked/evaluated-to-ambig.rs
deleted file mode 100644 (file)
index 0f36ce3..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// check-pass
-
-// We previously always returned ambiguity when equating generic consts, even if they
-// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1`
-// should fail.
-#![allow(incomplete_features)]
-#![feature(const_generics, const_evaluatable_checked)]
-
-enum Assert<const COND: bool> {}
-trait IsTrue {}
-impl IsTrue for Assert<true> {}
-
-struct Foo<const N: usize, const M: usize>;
-trait Bar<const N: usize, const M: usize> {}
-impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M>
-where
-    Assert<{ N > 1 }>: IsTrue,
-    Assert<{ M > 1 }>: IsTrue,
-{
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.full.stderr
deleted file mode 100644 (file)
index d6a54ea..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/feature-gate-const_evaluatable_checked.rs:8:30
-   |
-LL | fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
-   |                              ^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.min.stderr
deleted file mode 100644 (file)
index 7de4bfc..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/feature-gate-const_evaluatable_checked.rs:5:33
-   |
-LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs b/src/test/ui/const-generics/const_evaluatable_checked/feature-gate-const_evaluatable_checked.rs
deleted file mode 100644 (file)
index f49ca02..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-type Arr<const N: usize> = [u8; N - 1];
-//[min]~^ ERROR generic parameters may not be used in const operations
-
-fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
-    //[full]~^ ERROR constant expression depends
-    Default::default()
-}
-
-fn main() {
-    let x = test::<33>();
-    assert_eq!(x, [0; 32]);
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs b/src/test/ui/const-generics/const_evaluatable_checked/fn_call.rs
deleted file mode 100644 (file)
index c182f5e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-const fn test_me<T>(a: usize, b: usize) -> usize {
-    if a < b {
-        std::mem::size_of::<T>()
-    } else {
-        usize::MAX
-    }
-}
-
-fn test_simple<T>() -> [u8; std::mem::size_of::<T>()]
-where
-    [u8; std::mem::size_of::<T>()]: Sized,
-{
-    [0; std::mem::size_of::<T>()]
-}
-
-fn test_with_args<T, const N: usize>() -> [u8; test_me::<T>(N, N + 1) + N]
-where
-    [u8; test_me::<T>(N, N + 1) + N]: Sized,
-{
-    [0; test_me::<T>(N, N + 1) + N]
-}
-
-fn main() {
-    assert_eq!([0; 8], test_simple::<u64>());
-    assert_eq!([0; 12], test_with_args::<u64, 4>());
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs
deleted file mode 100644 (file)
index 8167d78..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn test<const N: usize>() -> [u8; N - 1] {
-    //~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed
-    todo!()
-}
-
-fn main() {
-    test::<0>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr
deleted file mode 100644 (file)
index 31ccf97..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed
-  --> $DIR/from-sig-fail.rs:4:35
-   |
-LL | fn test<const N: usize>() -> [u8; N - 1] {
-   |                                   ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs b/src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs
deleted file mode 100644 (file)
index 5c05a5a..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-struct Foo<const B: bool>;
-
-fn test<const N: usize>() -> Foo<{ N > 10 }> {
-    Foo
-}
-
-fn main() {
-    let _: Foo<true> = test::<12>();
-    let _: Foo<false> = test::<9>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/impl-bounds.rs b/src/test/ui/const-generics/const_evaluatable_checked/impl-bounds.rs
deleted file mode 100644 (file)
index 193a365..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// check-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-use std::mem::size_of;
-
-struct Foo<T, const N: usize>(T);
-
-impl<T> Foo<T, { size_of::<T>() }> {
-    fn test() {
-        let _: [u8; std::mem::size_of::<T>()];
-    }
-}
-
-trait Bar<const N: usize> {
-    fn test_me();
-}
-
-impl<T> Bar<{ size_of::<T>() }> for Foo<T, 3> {
-    fn test_me() {
-        let _: [u8; std::mem::size_of::<T>()];
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/infer-too-generic.rs b/src/test/ui/const-generics/const_evaluatable_checked/infer-too-generic.rs
deleted file mode 100644 (file)
index cad06ea..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-use std::{mem, ptr};
-
-fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1])
-where
-    [T; N - 1]: Sized,
-{
-    let arr = mem::ManuallyDrop::new(arr);
-    unsafe {
-        let head = ptr::read(&arr[0]);
-        let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]);
-        (head, tail)
-    }
-}
-
-fn main() {
-    let arr = [0, 1, 2, 3, 4];
-    let (head, tail) = split_first(arr);
-    assert_eq!(head, 0);
-    assert_eq!(tail, [1, 2, 3, 4]);
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/less_than.rs b/src/test/ui/const-generics/const_evaluatable_checked/less_than.rs
deleted file mode 100644 (file)
index 907ea25..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-struct Foo<const B: bool>;
-
-fn test<const N: usize>() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized {
-    Foo
-}
-
-fn main() {
-    let _: Foo<true> = test::<12>();
-    let _: Foo<false> = test::<9>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.rs
deleted file mode 100644 (file)
index a6bb392..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// We do not yet want to support let-bindings in abstract consts,
-// so this test should keep failing for now.
-fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-    //~^ ERROR overly complex generic constant
-    //~| ERROR overly complex generic constant
-    Default::default()
-}
-
-fn main() {
-    let x = test::<31>();
-    assert_eq!(x, [0; 32]);
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr b/src/test/ui/const-generics/const_evaluatable_checked/let-bindings.stderr
deleted file mode 100644 (file)
index 5749def..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error: overly complex generic constant
-  --> $DIR/let-bindings.rs:6:68
-   |
-LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                                                    ^^^^^^-^^^^^^^^^^^^^
-   |                                                                          |
-   |                                                                          unsupported statement
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: overly complex generic constant
-  --> $DIR/let-bindings.rs:6:35
-   |
-LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                   ^^^^^^-^^^^^^^^^^^^^
-   |                                         |
-   |                                         unsupported statement
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-1.rs
deleted file mode 100644 (file)
index 0fe84c1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn callee<const M2: usize>() -> usize
-where
-    [u8; M2 + 1]: Sized,
-{
-    M2
-}
-
-fn caller<const N1: usize>() -> usize
-where
-    [u8; N1 + 1]: Sized,
-    [u8; (N1 + 1) + 1]: Sized,
-{
-    callee::<{ N1 + 1 }>()
-}
-
-fn main() {
-    assert_eq!(caller::<4>(), 5);
-}
-
-// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee``
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested-abstract-consts-2.rs
deleted file mode 100644 (file)
index 4f58823..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// run-pass
-#![feature(const_evaluatable_checked, const_generics)]
-#![allow(incomplete_features)]
-
-struct Generic<const K: u64>;
-
-struct ConstU64<const K: u64>;
-
-impl<const K: u64> Generic<K>
-where
-    ConstU64<{ K - 1 }>: ,
-{
-    fn foo(self) -> u64 {
-        K
-    }
-}
-
-impl<const K: u64> Generic<K>
-where
-    ConstU64<{ K - 1 }>: ,
-    ConstU64<{ K + 1 }>: ,
-    ConstU64<{ K + 1 - 1 }>: ,
-{
-    fn bar(self) -> u64 {
-        let x: Generic<{ K + 1 }> = Generic;
-        x.foo()
-    }
-}
-
-fn main() {
-    assert_eq!((Generic::<10>).bar(), 11);
-}
-
-// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the
-// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-1.rs
deleted file mode 100644 (file)
index 4d0b87e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn zero_init<const N: usize>() -> Substs1<N>
-where
-    [u8; N + 1]: ,
-{
-    Substs1([0; N + 1])
-}
-struct Substs1<const N: usize>([u8; N + 1])
-where
-    [(); N + 1]: ;
-
-fn substs2<const M: usize>() -> Substs1<{ M * 2 }>
-where
-    [(); { M * 2 } + 1]: ,
-{
-    zero_init::<{ M * 2 }>()
-}
-
-fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
-where
-    [(); (L - 1) * 2 + 1]: ,
-{
-    substs2::<{ L - 1 }>()
-}
-
-fn main() {
-    assert_eq!(substs3::<2>().0, [0; 3]);
-}
-
-// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the
-// ``{ N + 1 }`` bound on ``Substs1``
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs b/src/test/ui/const-generics/const_evaluatable_checked/nested_uneval_unification-2.rs
deleted file mode 100644 (file)
index be8219a..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features, unused_parens, unused_braces)]
-
-fn zero_init<const N: usize>() -> Substs1<{ (N) }>
-where
-    [u8; { (N) }]: ,
-{
-    Substs1([0; { (N) }])
-}
-
-struct Substs1<const N: usize>([u8; { (N) }])
-where
-    [(); { (N) }]: ;
-
-fn substs2<const M: usize>() -> Substs1<{ (M) }> {
-    zero_init::<{ (M) }>()
-}
-
-fn substs3<const L: usize>() -> Substs1<{ (L) }> {
-    substs2::<{ (L) }>()
-}
-
-fn main() {
-    assert_eq!(substs3::<2>().0, [0; 2]);
-}
-
-// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the
-// ``{ (N) }`` bound on ``Substs1``
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.rs b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.rs
deleted file mode 100644 (file)
index 5be4b41..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-
-const fn bar<T: ?Sized>() -> usize { 7 }
-
-trait Foo {
-    fn test(&self) -> [u8; bar::<Self>()];
-}
-
-impl Foo for () {
-    fn test(&self) -> [u8; bar::<Self>()] {
-        [0; bar::<Self>()]
-    }
-}
-
-fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object
-    v.test();
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-ret.stderr
deleted file mode 100644 (file)
index 319e6c2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-ret.rs:17:16
-   |
-LL | fn use_dyn(v: &dyn Foo) {
-   |                ^^^^^^^ `Foo` cannot be made into an object
-   |
-   = help: consider moving `test` to another trait
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety-err-ret.rs:8:23
-   |
-LL | trait Foo {
-   |       --- this trait cannot be made into an object...
-LL |     fn test(&self) -> [u8; bar::<Self>()];
-   |                       ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.rs b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.rs
deleted file mode 100644 (file)
index 5fbd4a5..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-#![deny(where_clauses_object_safety)]
-
-
-const fn bar<T: ?Sized>() -> usize { 7 }
-
-trait Foo {
-    fn test(&self) where [u8; bar::<Self>()]: Sized;
-    //~^ ERROR the trait `Foo` cannot be made into an object
-    //~| WARN this was previously accepted by the compiler but is being phased out
-}
-
-impl Foo for () {
-    fn test(&self) where [u8; bar::<Self>()]: Sized {}
-}
-
-fn use_dyn(v: &dyn Foo) {
-    v.test();
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-err-where-bounds.stderr
deleted file mode 100644 (file)
index 45c7d83..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error: the trait `Foo` cannot be made into an object
-  --> $DIR/object-safety-err-where-bounds.rs:9:8
-   |
-LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
-   |        ^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/object-safety-err-where-bounds.rs:3:9
-   |
-LL | #![deny(where_clauses_object_safety)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/object-safety-err-where-bounds.rs:9:8
-   |
-LL | trait Foo {
-   |       --- this trait cannot be made into an object...
-LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
-   |        ^^^^ ...because method `test` references the `Self` type in its `where` clause
-   = help: consider moving `test` to another trait
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.rs b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.rs
deleted file mode 100644 (file)
index 9a95908..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait Foo<const N: usize> {
-    fn test(&self) -> [u8; N + 1];
-}
-
-impl<const N: usize> Foo<N> for () {
-    fn test(&self) -> [u8; N + 1] {
-        [0; N + 1]
-    }
-}
-
-fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
-    assert_eq!(v.test(), [0; N + 1]);
-}
-
-fn main() {
-    // FIXME(const_evaluatable_checked): Improve the error message here.
-    use_dyn(&());
-    //~^ ERROR type annotations needed
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.stderr b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok-infer-err.stderr
deleted file mode 100644 (file)
index ce75314..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0284]: type annotations needed: cannot satisfy `the constant `use_dyn::<{_: usize}>::{constant#0}` can be evaluated`
-  --> $DIR/object-safety-ok-infer-err.rs:20:5
-   |
-LL |     use_dyn(&());
-   |     ^^^^^^^ cannot satisfy `the constant `use_dyn::<{_: usize}>::{constant#0}` can be evaluated`
-   |
-note: required by a bound in `use_dyn`
-  --> $DIR/object-safety-ok-infer-err.rs:14:55
-   |
-LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
-   |                                                       ^^^^^ required by this bound in `use_dyn`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok.rs b/src/test/ui/const-generics/const_evaluatable_checked/object-safety-ok.rs
deleted file mode 100644 (file)
index ae78b79..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait Foo<const N: usize> {
-    fn test(&self) -> [u8; N + 1];
-}
-
-impl<const N: usize> Foo<N> for () {
-    fn test(&self) -> [u8; N + 1] {
-        [0; N + 1]
-    }
-}
-
-fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
-    assert_eq!(v.test(), [0; N + 1]);
-}
-
-fn main() {
-    use_dyn::<3>(&());
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
deleted file mode 100644 (file)
index 9f3d94b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/simple.rs:7:53
-   |
-LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
-   |                                                     ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/simple.rs:7:35
-   |
-LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
-   |                                   ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
deleted file mode 100644 (file)
index 94ad71b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// [full] run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![feature(const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
-    //[min]~^ ERROR generic parameters
-    //[min]~| ERROR generic parameters
-    Default::default()
-}
-
-fn main() {
-    let x = test::<33>();
-    assert_eq!(x, [0; 32]);
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.full.stderr
deleted file mode 100644 (file)
index 1f2313a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed
-  --> $DIR/simple_fail.rs:10:48
-   |
-LL | fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized {
-   |                                                ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
-
-error[E0080]: evaluation of `Arr::<0_usize>::{constant#0}` failed
-  --> $DIR/simple_fail.rs:6:33
-   |
-LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.min.stderr
deleted file mode 100644 (file)
index 1aa66f9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/simple_fail.rs:6:33
-   |
-LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/simple_fail.rs:10:48
-   |
-LL | fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized {
-   |                                                ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple_fail.rs
deleted file mode 100644 (file)
index f08d249..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, feature(const_evaluatable_checked))]
-#![allow(incomplete_features)]
-
-type Arr<const N: usize> = [u8; N - 1];
-//[min]~^ ERROR generic parameters may not be used in const operations
-//[full]~^^ ERROR evaluation of `Arr::<0_usize>::{constant#0}` failed
-
-fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized {
-//[min]~^ ERROR generic parameters may not be used in const operations
-//[full]~^^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed
-    todo!()
-}
-
-fn main() {
-    test::<0>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs b/src/test/ui/const-generics/const_evaluatable_checked/subexprs_are_const_evalutable.rs
deleted file mode 100644 (file)
index 11c0760..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn make_array<const M: usize>() -> [(); M + 1] {
-    [(); M + 1]
-}
-
-fn foo<const N: usize>() -> [(); (N * 2) + 1] {
-    make_array::<{ N * 2 }>()
-}
-
-fn main() {
-    assert_eq!(foo::<10>(), [(); 10 * 2 + 1])
-}
-
-// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs b/src/test/ui/const-generics/const_evaluatable_checked/ty-alias-substitution.rs
deleted file mode 100644 (file)
index 5c768a6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// Test that we correctly substitute generic arguments for type aliases.
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-type Alias<T, const N: usize> = [T; N + 1];
-
-fn foo<const M: usize>() -> Alias<u32, M>  where [u8; M + 1]: Sized {
-    [0; M + 1]
-}
-
-fn main() {
-    foo::<0>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unop.rs b/src/test/ui/const-generics/const_evaluatable_checked/unop.rs
deleted file mode 100644 (file)
index 8e0768b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-struct Foo<const B: bool>;
-
-fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized {
-    Foo
-}
-
-fn main() {
-    let _: Foo<false> = test::<12>();
-    let _: Foo<true> = test::<9>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused-complex-default-expr.rs
deleted file mode 100644 (file)
index 21f14f5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// check-pass
-#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
-#![allow(incomplete_features)]
-struct Foo<const N: usize, const M: usize = { N + 1 }>;
-struct Bar<const N: usize>(Foo<N, 3>);
-fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused_expr.rs b/src/test/ui/const-generics/const_evaluatable_checked/unused_expr.rs
deleted file mode 100644 (file)
index 9c603c5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-    //~^ ERROR overly complex generic constant
-    todo!()
-}
-
-fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-    //~^ ERROR overly complex generic constant
-    todo!()
-}
-
-const fn foo(n: usize) {}
-
-fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-    //~^ ERROR overly complex generic constant
-    todo!()
-}
-
-fn main() {
-    add::<12>();
-    div::<9>();
-    fn_call::<14>();
-}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/unused_expr.stderr b/src/test/ui/const-generics/const_evaluatable_checked/unused_expr.stderr
deleted file mode 100644 (file)
index 1687dbb..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error: overly complex generic constant
-  --> $DIR/unused_expr.rs:4:34
-   |
-LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: overly complex generic constant
-  --> $DIR/unused_expr.rs:9:34
-   |
-LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: overly complex generic constant
-  --> $DIR/unused_expr.rs:16:38
-   |
-LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-   |                                      ^^------^^^^^
-   |                                        |
-   |                                        dead code
-   |
-   = help: consider moving this anonymous constant into a `const` function
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs
new file mode 100644 (file)
index 0000000..8724fa6
--- /dev/null
@@ -0,0 +1,26 @@
+// build-pass
+
+#![feature(const_trait_impl)]
+
+trait Func<T> {
+    type Output;
+
+    fn call_once(self, arg: T) -> Self::Output;
+}
+
+
+struct Closure;
+
+impl const Func<&usize> for Closure {
+    type Output = usize;
+
+    fn call_once(self, arg: &usize) -> Self::Output {
+        *arg
+    }
+}
+
+enum Bug<T = [(); Closure.call_once(&0) ]> {
+    V(T),
+}
+
+fn main() {}
index b6fa478f48df4414aa661e795714823227fd9dbb..91410c4afdf750e0e3ff3d3e94db5e0b35164a59 100644 (file)
@@ -2,7 +2,7 @@
 // run-pass
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: u8>;
index 1d495c9562ded51c1e75d72eab8ad79d3dd107f3..ebde155f77656b582aa9211e1be1771176a66afa 100644 (file)
@@ -1,10 +1,6 @@
 // aux-build:crayte.rs
 // edition:2018
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 extern crate crayte;
 
 use crayte::*;
index 6514409698e3e6fda6c46dfd28083691563207f6..5c548740af2398aadf68efd026b32d43e5b42f38 100644 (file)
@@ -1,6 +1,4 @@
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 pub struct Defaulted<const N: usize=3>;
 impl Defaulted {
diff --git a/src/test/ui/const-generics/defaults/cec-concrete-default.rs b/src/test/ui/const-generics/defaults/cec-concrete-default.rs
deleted file mode 100644 (file)
index c2a41cf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
-#![allow(incomplete_features)]
-
-struct Foo<const N: usize, const M: usize = { N + 1 }>;
-fn no_constraining() -> Foo<10> {
-    Foo::<10, 11>
-}
-
-pub fn different_than_default() -> Foo<10> {
-    Foo::<10, 12>
-    //~^ error: mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-concrete-default.stderr b/src/test/ui/const-generics/defaults/cec-concrete-default.stderr
deleted file mode 100644 (file)
index 090e507..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/cec-concrete-default.rs:10:5
-   |
-LL |     Foo::<10, 12>
-   |     ^^^^^^^^^^^^^ expected `11_usize`, found `12_usize`
-   |
-   = note: expected type `11_usize`
-              found type `12_usize`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs b/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.rs
deleted file mode 100644 (file)
index 15822df..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked, const_generics_defaults)]
-#![allow(incomplete_features)]
-
-struct Foo<const N: usize, const M: usize = { N + 1 }>;
-fn should_unify<const N: usize>() -> Foo<N> where [(); { N + 1 }]: {
-    Foo::<N, { N + 1 }>
-}
-pub fn shouldnt_unify<const N: usize>() -> Foo<N>
-where
-    [(); { N + 1 }]:,
-    [(); { N + 2 }]:, {
-    Foo::<N, { N + 2 }>
-    //~^ error: mismatched types
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr b/src/test/ui/const-generics/defaults/cec-generic-default-mismatched-types.stderr
deleted file mode 100644 (file)
index f97fc26..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/cec-generic-default-mismatched-types.rs:12:5
-   |
-LL |     Foo::<N, { N + 2 }>
-   |     ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }`
-   |
-   = note: expected type `{ N + 1 }`
-              found type `{ N + 2 }`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default.rs b/src/test/ui/const-generics/defaults/cec-generic-default.rs
deleted file mode 100644 (file)
index 76ff7c7..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#![feature(const_evaluatable_checked, const_generics, const_generics_defaults)]
-#![allow(incomplete_features)]
-
-pub struct Foo<const N: usize, const M: usize = { N + 1 }>;
-pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
-    //~^ error: unconstrained generic constant
-    loop {}
-}
-pub fn has_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); N1 + 1]: {
-    loop {}
-}
-
-type FooAlias<const N: usize, const NP: usize = { N + 1 }> = [(); NP];
-fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
-{
-    //~^^ error: unconstrained generic constant
-    todo!()
-}
-fn has_evaluatable_bound_alias<const N: usize>() -> FooAlias<N>
-where [(); N + 1]: {
-    todo!()
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/defaults/cec-generic-default.stderr b/src/test/ui/const-generics/defaults/cec-generic-default.stderr
deleted file mode 100644 (file)
index 0234ea8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/cec-generic-default.rs:5:54
-   |
-LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
-   |                                                      ^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
-
-error: unconstrained generic constant
-  --> $DIR/cec-generic-default.rs:14:58
-   |
-LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
-   |                                                          ^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
-
-error: aborting due to 2 previous errors
-
index 44df2ac9f40fadb66034354973eb88cd1935ac74..aa289ec07783e764052b0770369bb5f4195eb8cb 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
    |                                               ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-generic-default-expr.rs:10:62
@@ -14,7 +14,7 @@ LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
    |                                                              ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
index d3558007977e46a9f10df41015548eafe1ebc0e6..814c996fbad6f50e88002ca6ee567cc22c132bc9 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 //[full] check-pass
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
index d24e403e017ef83222d56f27b3ef4c24a23bdc5e..c27ed298afd166f89abfcc55e22fa8ef894a03ca 100644 (file)
@@ -1,7 +1,7 @@
 // [full] run-pass
 // revisions: full min
 // Checks a complicated usage of unordered params
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(const_generics_defaults))]
 #![cfg_attr(full, allow(incomplete_features))]
 #![allow(dead_code)]
 
index 4fa21b8b1fb787b557a7bd52128425a6a8f3a6ba..e7cbf01a301790ae46843676245718ef4d72cbec 100644 (file)
@@ -1,9 +1,5 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
-
 
 pub struct ConstDefault<const N: usize = 3>;
 
index 8eb8f368b12f35926711bc29e5e55675a275c739..2b41dbb58873e348d77e784cb28bceca8dc56670 100644 (file)
@@ -1,13 +1,12 @@
 // run-pass
 #![feature(staged_api)]
-
-#![feature(const_generics)]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
-
+// FIXME(const_generics): It seems like we aren't testing the right thing here,
+// I would assume that we want the attributes to apply to the const parameter defaults
+// themselves.
 #![stable(feature = "const_default_test", since="none")]
 
-
 #[unstable(feature = "const_default_stable", issue="none")]
 pub struct ConstDefaultUnstable<const N: usize = 3>;
 
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.full.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr
deleted file mode 100644 (file)
index c417a26..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/default-on-impl.rs:8:12
-   |
-LL | impl<const N: usize = 1> Foo<N> {}
-   |            ^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr
deleted file mode 100644 (file)
index c417a26..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/default-on-impl.rs:8:12
-   |
-LL | impl<const N: usize = 1> Foo<N> {}
-   |            ^
-
-error: aborting due to previous error
-
index 735549defeaf07f9e5c35accf60917803098b000..280d92f839f4d45613abf8a3c44e5f4e08f9d060 100644 (file)
@@ -1,7 +1,4 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 struct Foo<const N: usize>;
 
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.stderr b/src/test/ui/const-generics/defaults/default-on-impl.stderr
new file mode 100644 (file)
index 0000000..0f85cec
--- /dev/null
@@ -0,0 +1,8 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/default-on-impl.rs:5:12
+   |
+LL | impl<const N: usize = 1> Foo<N> {}
+   |            ^
+
+error: aborting due to previous error
+
index 32acf567cf2b98d19012d742adf726381737629e..276e74355c25892e343c522d04431568e6a2078b 100644 (file)
@@ -1,9 +1,6 @@
 // aux-build:const_defaulty.rs
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 extern crate const_defaulty;
 use const_defaulty::Defaulted;
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.rs b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.rs
new file mode 100644 (file)
index 0000000..52cea51
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(generic_const_exprs, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+fn no_constraining() -> Foo<10> {
+    Foo::<10, 11>
+}
+
+pub fn different_than_default() -> Foo<10> {
+    Foo::<10, 12>
+    //~^ error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr b/src/test/ui/const-generics/defaults/generic-expr-default-concrete.stderr
new file mode 100644 (file)
index 0000000..905a285
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/generic-expr-default-concrete.rs:10:5
+   |
+LL |     Foo::<10, 12>
+   |     ^^^^^^^^^^^^^ expected `11_usize`, found `12_usize`
+   |
+   = note: expected type `11_usize`
+              found type `12_usize`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs b/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.rs
new file mode 100644 (file)
index 0000000..3a11631
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(generic_const_exprs, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+fn should_unify<const N: usize>() -> Foo<N> where [(); { N + 1 }]: {
+    Foo::<N, { N + 1 }>
+}
+pub fn shouldnt_unify<const N: usize>() -> Foo<N>
+where
+    [(); { N + 1 }]:,
+    [(); { N + 2 }]:, {
+    Foo::<N, { N + 2 }>
+    //~^ error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr b/src/test/ui/const-generics/defaults/generic-expr-default-mismatched-types.stderr
new file mode 100644 (file)
index 0000000..d5a3071
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/generic-expr-default-mismatched-types.rs:12:5
+   |
+LL |     Foo::<N, { N + 2 }>
+   |     ^^^^^^^^^^^^^^^^^^^ expected `{ N + 1 }`, found `{ N + 2 }`
+   |
+   = note: expected type `{ N + 1 }`
+              found type `{ N + 2 }`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default.rs b/src/test/ui/const-generics/defaults/generic-expr-default.rs
new file mode 100644 (file)
index 0000000..0adbd5c
--- /dev/null
@@ -0,0 +1,24 @@
+#![feature(generic_const_exprs, const_generics_defaults)]
+#![allow(incomplete_features)]
+
+pub struct Foo<const N: usize, const M: usize = { N + 1 }>;
+pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
+    //~^ error: unconstrained generic constant
+    loop {}
+}
+pub fn has_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); N1 + 1]: {
+    loop {}
+}
+
+type FooAlias<const N: usize, const NP: usize = { N + 1 }> = [(); NP];
+fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
+{
+    //~^^ error: unconstrained generic constant
+    todo!()
+}
+fn has_evaluatable_bound_alias<const N: usize>() -> FooAlias<N>
+where [(); N + 1]: {
+    todo!()
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/generic-expr-default.stderr b/src/test/ui/const-generics/defaults/generic-expr-default.stderr
new file mode 100644 (file)
index 0000000..ada1498
--- /dev/null
@@ -0,0 +1,18 @@
+error: unconstrained generic constant
+  --> $DIR/generic-expr-default.rs:5:54
+   |
+LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
+   |                                                      ^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
+
+error: unconstrained generic constant
+  --> $DIR/generic-expr-default.rs:14:58
+   |
+LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
+   |                                                          ^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
+
+error: aborting due to 2 previous errors
+
index 29d835e36c6eb74d9830d0cb2bcc25494235b0a3..725cc36b428c7a48fb08995836b435bb50e60136 100644 (file)
@@ -1,11 +1,11 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:7:28
+  --> $DIR/intermixed-lifetime.rs:5:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
    |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
 
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/intermixed-lifetime.rs:10:37
+  --> $DIR/intermixed-lifetime.rs:8:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
    |           --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
index 29d835e36c6eb74d9830d0cb2bcc25494235b0a3..725cc36b428c7a48fb08995836b435bb50e60136 100644 (file)
@@ -1,11 +1,11 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:7:28
+  --> $DIR/intermixed-lifetime.rs:5:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
    |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
 
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/intermixed-lifetime.rs:10:37
+  --> $DIR/intermixed-lifetime.rs:8:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
    |           --------------------------^^- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
index 307e3aaf1fbf38f532b155af97bdcf47b15c4942..cc215ab0c2517e1269f570ce38b040536c56c159 100644 (file)
@@ -1,8 +1,6 @@
 // Checks that lifetimes cannot be interspersed between consts and types.
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
 //~^ Error lifetime parameters must be declared prior to const parameters
diff --git a/src/test/ui/const-generics/defaults/mismatch.full.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr
deleted file mode 100644 (file)
index 4aa8401..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:12:28
-   |
-LL |     let e: Example::<13> = ();
-   |            -------------   ^^ expected struct `Example`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:34
-   |
-LL |     let e: Example2::<u32, 13> = ();
-   |            -------------------   ^^ expected struct `Example2`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example2`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:18:34
-   |
-LL |     let e: Example3::<13, u32> = ();
-   |            -------------------   ^^ expected struct `Example3`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example3`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:28
-   |
-LL |     let e: Example3::<7> = ();
-   |            -------------   ^^ expected struct `Example3`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example3<7_usize>`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:24:28
-   |
-LL |     let e: Example4::<7> = ();
-   |            -------------   ^^ expected struct `Example4`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example4<7_usize>`
-           found unit type `()`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr
deleted file mode 100644 (file)
index 4aa8401..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:12:28
-   |
-LL |     let e: Example::<13> = ();
-   |            -------------   ^^ expected struct `Example`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:34
-   |
-LL |     let e: Example2::<u32, 13> = ();
-   |            -------------------   ^^ expected struct `Example2`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example2`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:18:34
-   |
-LL |     let e: Example3::<13, u32> = ();
-   |            -------------------   ^^ expected struct `Example3`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example3`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:28
-   |
-LL |     let e: Example3::<7> = ();
-   |            -------------   ^^ expected struct `Example3`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example3<7_usize>`
-           found unit type `()`
-
-error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:24:28
-   |
-LL |     let e: Example4::<7> = ();
-   |            -------------   ^^ expected struct `Example4`, found `()`
-   |            |
-   |            expected due to this
-   |
-   = note: expected struct `Example4<7_usize>`
-           found unit type `()`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
index 9d9a8793aaac0e675ff94b2e1909733ea0fb2e7a..4ae93a9166d350534b25564f0d20401b63876544 100644 (file)
@@ -1,7 +1,4 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 pub struct Example<const N: usize=13>;
 pub struct Example2<T=u32, const N: usize=13>(T);
diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr
new file mode 100644 (file)
index 0000000..3c7f4fe
--- /dev/null
@@ -0,0 +1,58 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:9:28
+   |
+LL |     let e: Example::<13> = ();
+   |            -------------   ^^ expected struct `Example`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:12:34
+   |
+LL |     let e: Example2::<u32, 13> = ();
+   |            -------------------   ^^ expected struct `Example2`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example2`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:15:34
+   |
+LL |     let e: Example3::<13, u32> = ();
+   |            -------------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example3`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:18:28
+   |
+LL |     let e: Example3::<7> = ();
+   |            -------------   ^^ expected struct `Example3`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example3<7_usize>`
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:21:28
+   |
+LL |     let e: Example4::<7> = ();
+   |            -------------   ^^ expected struct `Example4`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Example4<7_usize>`
+           found unit type `()`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index a4006203e4a2730e9e6d0a95d2c34b15efa60240..158fa2ec1c8ffd614d2ef21c3b2cfe17471068e2 100644 (file)
@@ -1,5 +1,5 @@
 error: type parameters must be declared prior to const parameters
-  --> $DIR/needs-feature.rs:9:26
+  --> $DIR/needs-feature.rs:7:26
    |
 LL | struct A<const N: usize, T=u32>(T);
    |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T = u32, const N: usize>`
diff --git a/src/test/ui/const-generics/defaults/needs-feature.none.stderr b/src/test/ui/const-generics/defaults/needs-feature.none.stderr
deleted file mode 100644 (file)
index a400620..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameters must be declared prior to const parameters
-  --> $DIR/needs-feature.rs:9:26
-   |
-LL | struct A<const N: usize, T=u32>(T);
-   |         -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T = u32, const N: usize>`
-
-error: aborting due to previous error
-
index b58dee0712a767826502e5e7e6a5ca8feea7e094..9ba8184e058518a21501c2ffa7451b0a63d90a76 100644 (file)
@@ -1,10 +1,8 @@
 //[full] run-pass
 // Verifies that having generic parameters after constants is not permitted without the
-// `const_generics` feature.
+// `const_generics_defaults` feature.
 // revisions: min full
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(full, feature(const_generics_defaults))]
 
 struct A<const N: usize, T=u32>(T);
 //[min]~^ ERROR type parameters must be declared prior
index c003cb2c5a6ee556d9723169e95bd14acc980453..bc01fe2656c9b066bd160863e59344d6807c7b98 100644 (file)
@@ -1,9 +1,6 @@
 // run-pass
 // Checks that type param defaults are allowed after const params.
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 #![allow(dead_code)]
 
 struct FixedOutput<'a, const N: usize, T=u32> {
index e68075ee3c627e24cdc2db8ebd1be70bb45f39d5..8b35c5860d9419462dae82af2b32fd4370cc225d 100644 (file)
@@ -1,8 +1,5 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 struct N;
 
diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
deleted file mode 100644 (file)
index eb0bcb2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:6:10
-   |
-LL | struct A<T = u32, const N: usize> {
-   |          ^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
deleted file mode 100644 (file)
index eb0bcb2..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:6:10
-   |
-LL | struct A<T = u32, const N: usize> {
-   |          ^
-
-error: aborting due to previous error
-
index 88e9e96ba43f961ef071a49a0f5ff147d62bd1ae..33564a48448a79eb2e0e61e19c2c5a60ea1d1c4d 100644 (file)
@@ -1,7 +1,4 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features)]
 
 struct A<T = u32, const N: usize> {
     //~^ ERROR generic parameters with a default must be trailing
diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.stderr
new file mode 100644 (file)
index 0000000..47a2c6f
--- /dev/null
@@ -0,0 +1,8 @@
+error: generic parameters with a default must be trailing
+  --> $DIR/wrong-order.rs:3:10
+   |
+LL | struct A<T = u32, const N: usize> {
+   |          ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.rs b/src/test/ui/const-generics/derive-debug-array-wrapper.rs
deleted file mode 100644 (file)
index ce1481d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Check that deriving debug on struct with const is permitted.
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-#[derive(Debug)]
-struct X<const N: usize> {
-    a: [u32; N],
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/diagnostics.rs b/src/test/ui/const-generics/diagnostics.rs
deleted file mode 100644 (file)
index 1581af5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![crate_type="lib"]
-#![feature(min_const_generics)]
-#![allow(incomplete_features)]
-
-struct A<const N: u8>;
-trait Foo {}
-impl Foo for A<N> {}
-//~^ ERROR cannot find type
-//~| unresolved item provided when a constant
-
-struct B<const N: u8>;
-impl<N> Foo for B<N> {}
-//~^ ERROR type provided when a constant
-
-struct C<const C: u8, const N: u8>;
-impl<const N: u8> Foo for C<N, T> {}
-//~^ ERROR cannot find type
-//~| unresolved item provided when a constant
diff --git a/src/test/ui/const-generics/diagnostics.stderr b/src/test/ui/const-generics/diagnostics.stderr
deleted file mode 100644 (file)
index dd37d4e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-error[E0412]: cannot find type `N` in this scope
-  --> $DIR/diagnostics.rs:7:16
-   |
-LL | struct A<const N: u8>;
-   | ---------------------- similarly named struct `A` defined here
-LL | trait Foo {}
-LL | impl Foo for A<N> {}
-   |                ^
-   |
-help: a struct with a similar name exists
-   |
-LL | impl Foo for A<A> {}
-   |                ~
-help: you might be missing a type parameter
-   |
-LL | impl<N> Foo for A<N> {}
-   |     +++
-
-error[E0412]: cannot find type `T` in this scope
-  --> $DIR/diagnostics.rs:16:32
-   |
-LL | struct A<const N: u8>;
-   | ---------------------- similarly named struct `A` defined here
-...
-LL | impl<const N: u8> Foo for C<N, T> {}
-   |                                ^
-   |
-help: a struct with a similar name exists
-   |
-LL | impl<const N: u8> Foo for C<N, A> {}
-   |                                ~
-help: you might be missing a type parameter
-   |
-LL | impl<const N: u8, T> Foo for C<N, T> {}
-   |                 +++
-
-error[E0747]: unresolved item provided when a constant was expected
-  --> $DIR/diagnostics.rs:7:16
-   |
-LL | impl Foo for A<N> {}
-   |                ^
-   |
-help: if this generic argument was intended as a const parameter, surround it with braces
-   |
-LL | impl Foo for A<{ N }> {}
-   |                +   +
-
-error[E0747]: type provided when a constant was expected
-  --> $DIR/diagnostics.rs:12:19
-   |
-LL | impl<N> Foo for B<N> {}
-   |                   ^
-   |
-help: consider changing this type parameter to be a `const` generic
-   |
-LL | impl<const N: u8> Foo for B<N> {}
-   |      ~~~~~~~~~~~
-
-error[E0747]: unresolved item provided when a constant was expected
-  --> $DIR/diagnostics.rs:16:32
-   |
-LL | impl<const N: u8> Foo for C<N, T> {}
-   |                                ^
-   |
-help: if this generic argument was intended as a const parameter, surround it with braces
-   |
-LL | impl<const N: u8> Foo for C<N, { T }> {}
-   |                                +   +
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0412, E0747.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/const-generics/different_byref.full.stderr b/src/test/ui/const-generics/different_byref.full.stderr
deleted file mode 100644 (file)
index d6b3232..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/different_byref.rs:12:9
-   |
-LL |     x = Const::<{ [4] }> {};
-   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
-   |
-   = note: expected type `[3_usize]`
-              found type `[4_usize]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr
deleted file mode 100644 (file)
index 93874fb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `[usize; 1]` is forbidden as the type of a const generic parameter
-  --> $DIR/different_byref.rs:7:23
-   |
-LL | struct Const<const V: [usize; 1]> {}
-   |                       ^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/different_byref.rs b/src/test/ui/const-generics/different_byref.rs
deleted file mode 100644 (file)
index 7977560..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Check that different const types are different.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct Const<const V: [usize; 1]> {}
-//[min]~^ ERROR `[usize; 1]` is forbidden
-
-fn main() {
-    let mut x = Const::<{ [3] }> {};
-    x = Const::<{ [4] }> {};
-    //[full]~^ ERROR mismatched types
-}
diff --git a/src/test/ui/const-generics/different_byref_simple.full.stderr b/src/test/ui/const-generics/different_byref_simple.full.stderr
deleted file mode 100644 (file)
index 027e282..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/different_byref_simple.rs:11:9
-   |
-LL |     u = ConstUsize::<4> {};
-   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
-   |
-   = note: expected struct `ConstUsize<3_usize>`
-              found struct `ConstUsize<4_usize>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref_simple.min.stderr b/src/test/ui/const-generics/different_byref_simple.min.stderr
deleted file mode 100644 (file)
index 027e282..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/different_byref_simple.rs:11:9
-   |
-LL |     u = ConstUsize::<4> {};
-   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
-   |
-   = note: expected struct `ConstUsize<3_usize>`
-              found struct `ConstUsize<4_usize>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_byref_simple.rs b/src/test/ui/const-generics/different_byref_simple.rs
deleted file mode 100644 (file)
index b48189f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Check that different const types are different.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct ConstUsize<const V: usize> {}
-
-fn main() {
-    let mut u = ConstUsize::<3> {};
-    u = ConstUsize::<4> {};
-    //~^ ERROR mismatched types
-}
diff --git a/src/test/ui/const-generics/different_generic_args.full.stderr b/src/test/ui/const-generics/different_generic_args.full.stderr
new file mode 100644 (file)
index 0000000..a2dcc03
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_generic_args.rs:11:9
+   |
+LL |     u = ConstUsize::<4> {};
+   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected struct `ConstUsize<3_usize>`
+              found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_generic_args.min.stderr b/src/test/ui/const-generics/different_generic_args.min.stderr
new file mode 100644 (file)
index 0000000..a2dcc03
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_generic_args.rs:11:9
+   |
+LL |     u = ConstUsize::<4> {};
+   |         ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected struct `ConstUsize<3_usize>`
+              found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/different_generic_args.rs b/src/test/ui/const-generics/different_generic_args.rs
new file mode 100644 (file)
index 0000000..9ee0e07
--- /dev/null
@@ -0,0 +1,13 @@
+// Check that types with different const arguments are different.
+// revisions: full min
+
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct ConstUsize<const V: usize> {}
+
+fn main() {
+    let mut u = ConstUsize::<3> {};
+    u = ConstUsize::<4> {};
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/different_generic_args_array.rs b/src/test/ui/const-generics/different_generic_args_array.rs
new file mode 100644 (file)
index 0000000..4d225df
--- /dev/null
@@ -0,0 +1,11 @@
+// Check that different const types are different.
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
+
+struct Const<const V: [usize; 1]> {}
+
+fn main() {
+    let mut x = Const::<{ [3] }> {};
+    x = Const::<{ [4] }> {};
+    //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/different_generic_args_array.stderr b/src/test/ui/const-generics/different_generic_args_array.stderr
new file mode 100644 (file)
index 0000000..c0709a9
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/different_generic_args_array.rs:9:9
+   |
+LL |     x = Const::<{ [4] }> {};
+   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |
+   = note: expected struct `Const<[3_usize]>`
+              found struct `Const<[4_usize]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index afef748ff46906a2f30a5d335446aa4f04f97885..6c4ee1af210ba2db5122a84415d47e730476efc4 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // This tests that during error handling for the "trait not implemented" error
index 73ed23521c30c57f16306d98e450b249664fd7e8..3dee326a186e9c84f387483c1b0a90476eaee853 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait Foo<const N: usize> {
     fn myfun(&self) -> usize;
diff --git a/src/test/ui/const-generics/early/closing-args-token.rs b/src/test/ui/const-generics/early/closing-args-token.rs
new file mode 100644 (file)
index 0000000..cb4d629
--- /dev/null
@@ -0,0 +1,26 @@
+struct S<const X: u32>;
+struct T<const X: bool>;
+
+fn bad_args_1() {
+    S::<5 + 2 >> 7>;
+    //~^ ERROR expressions must be enclosed in braces to be used as const generic arguments
+    //~| ERROR comparison operators cannot be chained
+}
+
+fn bad_args_2() {
+    S::<{ 5 + 2 } >> 7>;
+    //~^ ERROR comparison operators cannot be chained
+}
+
+fn bad_args_3() {
+    T::<0 >= 3>;
+    //~^ ERROR expected expression, found `;`
+}
+
+fn bad_args_4() {
+    let mut x = 0;
+    T::<x >>= 2 > 0>;
+    //~^ ERROR comparison operators cannot be chained
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/early/closing-args-token.stderr b/src/test/ui/const-generics/early/closing-args-token.stderr
new file mode 100644 (file)
index 0000000..58fff3a
--- /dev/null
@@ -0,0 +1,52 @@
+error: expressions must be enclosed in braces to be used as const generic arguments
+  --> $DIR/closing-args-token.rs:5:9
+   |
+LL |     S::<5 + 2 >> 7>;
+   |         ^^^^^
+   |
+help: enclose the `const` expression in braces
+   |
+LL |     S::<{ 5 + 2 } >> 7>;
+   |         +       +
+
+error: comparison operators cannot be chained
+  --> $DIR/closing-args-token.rs:5:16
+   |
+LL |     S::<5 + 2 >> 7>;
+   |                ^  ^
+   |
+help: split the comparison into two
+   |
+LL |     S::<5 + 2 >> 7 && 7>;
+   |                    ++++
+
+error: comparison operators cannot be chained
+  --> $DIR/closing-args-token.rs:11:20
+   |
+LL |     S::<{ 5 + 2 } >> 7>;
+   |                    ^  ^
+   |
+help: split the comparison into two
+   |
+LL |     S::<{ 5 + 2 } >> 7 && 7>;
+   |                        ++++
+
+error: expected expression, found `;`
+  --> $DIR/closing-args-token.rs:16:16
+   |
+LL |     T::<0 >= 3>;
+   |                ^ expected expression
+
+error: comparison operators cannot be chained
+  --> $DIR/closing-args-token.rs:22:12
+   |
+LL |     T::<x >>= 2 > 0>;
+   |            ^^   ^
+   |
+help: split the comparison into two
+   |
+LL |     T::<x >>= 2 && 2 > 0>;
+   |                 ++++
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/const-generics/early/const-expression-parameter.rs b/src/test/ui/const-generics/early/const-expression-parameter.rs
new file mode 100644 (file)
index 0000000..4cf7ba8
--- /dev/null
@@ -0,0 +1,19 @@
+fn i32_identity<const X: i32>() -> i32 {
+    5
+}
+
+fn foo_a() {
+    i32_identity::<-1>(); // ok
+}
+
+fn foo_b() {
+    i32_identity::<1 + 2>(); //~ ERROR expressions must be enclosed in braces
+}
+
+fn foo_c() {
+    i32_identity::< -1 >(); // ok
+}
+
+fn main() {
+    i32_identity::<5>(); // ok
+}
diff --git a/src/test/ui/const-generics/early/const-expression-parameter.stderr b/src/test/ui/const-generics/early/const-expression-parameter.stderr
new file mode 100644 (file)
index 0000000..4ce1be2
--- /dev/null
@@ -0,0 +1,13 @@
+error: expressions must be enclosed in braces to be used as const generic arguments
+  --> $DIR/const-expression-parameter.rs:10:20
+   |
+LL |     i32_identity::<1 + 2>();
+   |                    ^^^^^
+   |
+help: enclose the `const` expression in braces
+   |
+LL |     i32_identity::<{ 1 + 2 }>();
+   |                    +       +
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/early/const-param-from-outer-fn.rs b/src/test/ui/const-generics/early/const-param-from-outer-fn.rs
new file mode 100644 (file)
index 0000000..c3b418e
--- /dev/null
@@ -0,0 +1,7 @@
+fn foo<const X: u32>() {
+    fn bar() -> u32 {
+        X //~ ERROR can't use generic parameters from outer function
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/early/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/early/const-param-from-outer-fn.stderr
new file mode 100644 (file)
index 0000000..a9f9787
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/const-param-from-outer-fn.rs:3:9
+   |
+LL | fn foo<const X: u32>() {
+   |              - const parameter from outer function
+LL |     fn bar() -> u32 {
+   |        --- try adding a local generic parameter in this method instead
+LL |         X
+   |         ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
diff --git a/src/test/ui/const-generics/early/const-param-hygiene.rs b/src/test/ui/const-generics/early/const-param-hygiene.rs
new file mode 100644 (file)
index 0000000..fd4e5b4
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+
+macro_rules! bar {
+    ($($t:tt)*) => { impl<const N: usize> $($t)* };
+}
+
+macro_rules! baz {
+    ($t:tt) => { fn test<const M: usize>(&self) -> usize { $t } };
+}
+
+struct Foo<const N: usize>;
+
+bar!(Foo<N> { baz!{ M } });
+
+fn main() {
+    assert_eq!(Foo::<7>.test::<3>(), 3);
+}
diff --git a/src/test/ui/const-generics/early/const-param-shadowing.rs b/src/test/ui/const-generics/early/const-param-shadowing.rs
new file mode 100644 (file)
index 0000000..ddd15db
--- /dev/null
@@ -0,0 +1,7 @@
+type N = u32;
+struct Foo<const M: usize>;
+fn test<const N: usize>() -> Foo<N> { //~ ERROR type provided when
+    Foo
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/early/const-param-shadowing.stderr b/src/test/ui/const-generics/early/const-param-shadowing.stderr
new file mode 100644 (file)
index 0000000..625338b
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0747]: type provided when a constant was expected
+  --> $DIR/const-param-shadowing.rs:3:34
+   |
+LL | fn test<const N: usize>() -> Foo<N> {
+   |                                  ^
+   |
+help: if this generic argument was intended as a const parameter, surround it with braces
+   |
+LL | fn test<const N: usize>() -> Foo<{ N }> {
+   |                                  +   +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/early/invalid-const-arguments.rs b/src/test/ui/const-generics/early/invalid-const-arguments.rs
new file mode 100644 (file)
index 0000000..6619c97
--- /dev/null
@@ -0,0 +1,16 @@
+#![crate_type="lib"]
+
+struct A<const N: u8>;
+trait Foo {}
+impl Foo for A<N> {}
+//~^ ERROR cannot find type
+//~| unresolved item provided when a constant
+
+struct B<const N: u8>;
+impl<N> Foo for B<N> {}
+//~^ ERROR type provided when a constant
+
+struct C<const C: u8, const N: u8>;
+impl<const N: u8> Foo for C<N, T> {}
+//~^ ERROR cannot find type
+//~| unresolved item provided when a constant
diff --git a/src/test/ui/const-generics/early/invalid-const-arguments.stderr b/src/test/ui/const-generics/early/invalid-const-arguments.stderr
new file mode 100644 (file)
index 0000000..b46e7e2
--- /dev/null
@@ -0,0 +1,73 @@
+error[E0412]: cannot find type `N` in this scope
+  --> $DIR/invalid-const-arguments.rs:5:16
+   |
+LL | struct A<const N: u8>;
+   | ---------------------- similarly named struct `A` defined here
+LL | trait Foo {}
+LL | impl Foo for A<N> {}
+   |                ^
+   |
+help: a struct with a similar name exists
+   |
+LL | impl Foo for A<A> {}
+   |                ~
+help: you might be missing a type parameter
+   |
+LL | impl<N> Foo for A<N> {}
+   |     +++
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/invalid-const-arguments.rs:14:32
+   |
+LL | struct A<const N: u8>;
+   | ---------------------- similarly named struct `A` defined here
+...
+LL | impl<const N: u8> Foo for C<N, T> {}
+   |                                ^
+   |
+help: a struct with a similar name exists
+   |
+LL | impl<const N: u8> Foo for C<N, A> {}
+   |                                ~
+help: you might be missing a type parameter
+   |
+LL | impl<const N: u8, T> Foo for C<N, T> {}
+   |                 +++
+
+error[E0747]: unresolved item provided when a constant was expected
+  --> $DIR/invalid-const-arguments.rs:5:16
+   |
+LL | impl Foo for A<N> {}
+   |                ^
+   |
+help: if this generic argument was intended as a const parameter, surround it with braces
+   |
+LL | impl Foo for A<{ N }> {}
+   |                +   +
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/invalid-const-arguments.rs:10:19
+   |
+LL | impl<N> Foo for B<N> {}
+   |                   ^
+   |
+help: consider changing this type parameter to be a `const` generic
+   |
+LL | impl<const N: u8> Foo for B<N> {}
+   |      ~~~~~~~~~~~
+
+error[E0747]: unresolved item provided when a constant was expected
+  --> $DIR/invalid-const-arguments.rs:14:32
+   |
+LL | impl<const N: u8> Foo for C<N, T> {}
+   |                                ^
+   |
+help: if this generic argument was intended as a const parameter, surround it with braces
+   |
+LL | impl<const N: u8> Foo for C<N, { T }> {}
+   |                                +   +
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0412, E0747.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/const-generics/early/macro_rules-braces.rs b/src/test/ui/const-generics/early/macro_rules-braces.rs
new file mode 100644 (file)
index 0000000..0ae9146
--- /dev/null
@@ -0,0 +1,73 @@
+mod m {
+    pub const P: usize = 0;
+}
+
+const Q: usize = 0;
+
+fn test<const N: usize>() {
+    struct Foo<const M: usize>;
+    macro_rules! foo {
+        ($x:expr) => {
+            [u8; $x]
+        }
+    }
+    macro_rules! bar {
+        ($x:expr) => {
+            [u8; { $x }]
+        }
+    }
+    macro_rules! baz {
+        ( $x:expr) => {
+            Foo<$x>
+        }
+    }
+    macro_rules! biz {
+        ($x:expr) => {
+            Foo<{ $x }>
+        };
+    }
+
+    let _: foo!(N);
+    let _: foo!({ N });
+    let _: foo!({{ N }}); //~ ERROR generic parameters may not
+    let _: foo!(Q);
+    let _: foo!(m::P);
+    let _: bar!(N);
+    let _: bar!({ N }); //~ ERROR generic parameters may not
+    let _: bar!(Q);
+    let _: bar!(m::P);
+    let _: baz!(N);
+    let _: baz!({ N });
+    let _: baz!({{ N }}); //~ ERROR generic parameters may not
+    let _: baz!(Q);
+    let _: baz!({ m::P });
+    let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces
+    let _: biz!(N);
+    let _: biz!({ N }); //~ ERROR generic parameters may not
+    let _: biz!(Q);
+    let _: biz!(m::P);
+    let _: foo!(3);
+    let _: foo!({ 3 });
+    let _: foo!({{ 3 }});
+    let _: bar!(3);
+    let _: bar!({ 3 });
+    let _: baz!(3);
+    let _: baz!({ 3 });
+    let _: baz!({{ 3 }});
+    let _: biz!(3);
+    let _: biz!({ 3 });
+    let _: foo!(10 + 7);
+    let _: foo!({ 10 + 7 });
+    let _: foo!({{ 10 + 7 }});
+    let _: bar!(10 + 7);
+    let _: bar!({ 10 + 7 });
+    let _: baz!(10 + 7); //~ ERROR expressions must be enclosed in braces
+    let _: baz!({ 10 + 7 });
+    let _: baz!({{ 10 + 7 }});
+    let _: biz!(10 + 7);
+    let _: biz!({ 10 + 7 });
+}
+
+fn main() {
+    test::<3>();
+}
diff --git a/src/test/ui/const-generics/early/macro_rules-braces.stderr b/src/test/ui/const-generics/early/macro_rules-braces.stderr
new file mode 100644 (file)
index 0000000..49382db
--- /dev/null
@@ -0,0 +1,60 @@
+error: expressions must be enclosed in braces to be used as const generic arguments
+  --> $DIR/macro_rules-braces.rs:44:17
+   |
+LL |     let _: baz!(m::P);
+   |                 ^^^^
+   |
+help: enclose the `const` expression in braces
+   |
+LL |     let _: baz!({ m::P });
+   |                 +      +
+
+error: expressions must be enclosed in braces to be used as const generic arguments
+  --> $DIR/macro_rules-braces.rs:64:17
+   |
+LL |     let _: baz!(10 + 7);
+   |                 ^^^^^^
+   |
+help: enclose the `const` expression in braces
+   |
+LL |     let _: baz!({ 10 + 7 });
+   |                 +        +
+
+error: generic parameters may not be used in const operations
+  --> $DIR/macro_rules-braces.rs:32:20
+   |
+LL |     let _: foo!({{ N }});
+   |                    ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/macro_rules-braces.rs:36:19
+   |
+LL |     let _: bar!({ N });
+   |                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/macro_rules-braces.rs:41:20
+   |
+LL |     let _: baz!({{ N }});
+   |                    ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/macro_rules-braces.rs:46:19
+   |
+LL |     let _: biz!({ N });
+   |                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/const-generics/exhaustive-value.full.stderr b/src/test/ui/const-generics/exhaustive-value.full.stderr
deleted file mode 100644 (file)
index 4e89e4a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0277]: the trait bound `(): Foo<N>` is not satisfied
-  --> $DIR/exhaustive-value.rs:266:5
-   |
-LL |     <() as Foo<N>>::test()
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <() as Foo<0_u8>>
-             <() as Foo<100_u8>>
-             <() as Foo<101_u8>>
-             <() as Foo<102_u8>>
-           and 252 others
-note: required by `Foo::test`
-  --> $DIR/exhaustive-value.rs:6:5
-   |
-LL |     fn test() {}
-   |     ^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/exhaustive-value.min.stderr b/src/test/ui/const-generics/exhaustive-value.min.stderr
deleted file mode 100644 (file)
index 4e89e4a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0277]: the trait bound `(): Foo<N>` is not satisfied
-  --> $DIR/exhaustive-value.rs:266:5
-   |
-LL |     <() as Foo<N>>::test()
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
-   |
-   = help: the following implementations were found:
-             <() as Foo<0_u8>>
-             <() as Foo<100_u8>>
-             <() as Foo<101_u8>>
-             <() as Foo<102_u8>>
-           and 252 others
-note: required by `Foo::test`
-  --> $DIR/exhaustive-value.rs:6:5
-   |
-LL |     fn test() {}
-   |     ^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index 921f9a467078b31d76fa5030da9401d12a958edd..778d498343e08739eb29dd5fce2dbb46cccb6d2a 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait Foo<const N: u8> {
     fn test() {}
 }
diff --git a/src/test/ui/const-generics/exhaustive-value.stderr b/src/test/ui/const-generics/exhaustive-value.stderr
new file mode 100644 (file)
index 0000000..0c6aced
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `(): Foo<N>` is not satisfied
+  --> $DIR/exhaustive-value.rs:262:5
+   |
+LL |     <() as Foo<N>>::test()
+   |     ^^^^^^^^^^^^^^^^^^^^ the trait `Foo<N>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<0_u8>>
+             <() as Foo<100_u8>>
+             <() as Foo<101_u8>>
+             <() as Foo<102_u8>>
+           and 252 others
+note: required by `Foo::test`
+  --> $DIR/exhaustive-value.rs:2:5
+   |
+LL |     fn test() {}
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 70a104e22227d44142e432eff03792e39979330d..dc516fb71c4b406a60348e76d47e3cdf6779d1e4 100644 (file)
@@ -1,7 +1,7 @@
 // Check that functions cannot be used as const parameters.
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn function() -> u32 {
index d090479d4c30b3eb2f50d210120229712afc5f9e..22f5f529c76ab128e40b8b6682a32df7ad6bfacd 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Checked<const F: fn(usize) -> bool>;
diff --git a/src/test/ui/const-generics/fn-taking-const-generic-array.rs b/src/test/ui/const-generics/fn-taking-const-generic-array.rs
deleted file mode 100644 (file)
index 58c1b95..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-use std::fmt::Display;
-
-fn print_slice<T: Display, const N: usize>(slice: &[T; N]) {
-    for x in slice.iter() {
-        println!("{}", x);
-    }
-}
-
-fn main() {
-    print_slice(&[1, 2, 3]);
-}
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.full.stderr
deleted file mode 100644 (file)
index 5c0f175..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
-  --> $DIR/forbid-non-structural_match-types.rs:14:19
-   |
-LL | struct D<const X: C>;
-   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
deleted file mode 100644 (file)
index 80eac99..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error: `A` is forbidden as the type of a const generic parameter
-  --> $DIR/forbid-non-structural_match-types.rs:9:19
-   |
-LL | struct B<const X: A>; // ok
-   |                   ^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: `C` is forbidden as the type of a const generic parameter
-  --> $DIR/forbid-non-structural_match-types.rs:14:19
-   |
-LL | struct D<const X: C>;
-   |                   ^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
-  --> $DIR/forbid-non-structural_match-types.rs:14:19
-   |
-LL | struct D<const X: C>;
-   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0741`.
index 0fdb3ed4a5a7989c4db5247403c94be31936f7dd..6ae9d5cfbb54f42df0ab52452de4141b705bceeb 100644 (file)
@@ -1,17 +1,13 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
 
 #[derive(PartialEq, Eq)]
 struct A;
 
 struct B<const X: A>; // ok
-//[min]~^ ERROR `A` is forbidden
 
 struct C;
 
 struct D<const X: C>; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]`
-//[min]~^ ERROR `C` is forbidden
 
 fn main() {}
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr
new file mode 100644 (file)
index 0000000..81b9bdf
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+  --> $DIR/forbid-non-structural_match-types.rs:11:19
+   |
+LL | struct D<const X: C>;
+   |                   ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.full.stderr
deleted file mode 100644 (file)
index b827e48..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0044]: foreign items may not have const parameters
-  --> $DIR/foreign-item-const-parameter.rs:7:5
-   |
-LL |     fn foo<const X: usize>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
-   |
-   = help: replace the const parameters with concrete consts
-
-error[E0044]: foreign items may not have type or const parameters
-  --> $DIR/foreign-item-const-parameter.rs:9:5
-   |
-LL |     fn bar<T, const X: usize>(_: T);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
-   |
-   = help: replace the type or const parameters with concrete types or consts
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.min.stderr
deleted file mode 100644 (file)
index b827e48..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0044]: foreign items may not have const parameters
-  --> $DIR/foreign-item-const-parameter.rs:7:5
-   |
-LL |     fn foo<const X: usize>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
-   |
-   = help: replace the const parameters with concrete consts
-
-error[E0044]: foreign items may not have type or const parameters
-  --> $DIR/foreign-item-const-parameter.rs:9:5
-   |
-LL |     fn bar<T, const X: usize>(_: T);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
-   |
-   = help: replace the type or const parameters with concrete types or consts
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0044`.
index 83caa89f033009eefd4b2f922809f6bba888ccfd..4fe377b5964f74a43f6b5cd08db2cd6f0218d09d 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 extern "C" {
     fn foo<const X: usize>(); //~ ERROR foreign items may not have const parameters
 
diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.stderr
new file mode 100644 (file)
index 0000000..b02db87
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0044]: foreign items may not have const parameters
+  --> $DIR/foreign-item-const-parameter.rs:2:5
+   |
+LL |     fn foo<const X: usize>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+   |
+   = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+  --> $DIR/foreign-item-const-parameter.rs:4:5
+   |
+LL |     fn bar<T, const X: usize>(_: T);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+   |
+   = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr b/src/test/ui/const-generics/generic-function-call-in-array-length.full.stderr
deleted file mode 100644 (file)
index 2d19a58..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/generic-function-call-in-array-length.rs:8:29
-   |
-LL | fn bar<const N: usize>() -> [u32; foo(N)] {
-   |                             ^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr b/src/test/ui/const-generics/generic-function-call-in-array-length.min.stderr
deleted file mode 100644 (file)
index d7a3f04..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/generic-function-call-in-array-length.rs:8:39
-   |
-LL | fn bar<const N: usize>() -> [u32; foo(N)] {
-   |                                       ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/generic-function-call-in-array-length.rs:11:13
-   |
-LL |     [0; foo(N)]
-   |             ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/generic-function-call-in-array-length.rs b/src/test/ui/const-generics/generic-function-call-in-array-length.rs
deleted file mode 100644 (file)
index a6d2bbd..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-const fn foo(n: usize) -> usize { n * 2 }
-
-fn bar<const N: usize>() -> [u32; foo(N)] {
-    //[min]~^ ERROR generic parameters may not be used in const operations
-    //[full]~^^ ERROR constant expression depends on a generic parameter
-    [0; foo(N)]
-    //[min]~^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/generic-param-mismatch.full.stderr b/src/test/ui/const-generics/generic-param-mismatch.full.stderr
deleted file mode 100644 (file)
index aff8780..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/generic-param-mismatch.rs:6:5
-   |
-LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
-   |                                              ------- expected `[u8; M]` because of return type
-LL |     [0; N]
-   |     ^^^^^^ expected `M`, found `N`
-   |
-   = note: expected array `[u8; M]`
-              found array `[u8; N]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic-param-mismatch.min.stderr b/src/test/ui/const-generics/generic-param-mismatch.min.stderr
deleted file mode 100644 (file)
index aff8780..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/generic-param-mismatch.rs:6:5
-   |
-LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
-   |                                              ------- expected `[u8; M]` because of return type
-LL |     [0; N]
-   |     ^^^^^^ expected `M`, found `N`
-   |
-   = note: expected array `[u8; M]`
-              found array `[u8; N]`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
index 22fffe47dcc2f5c91941de8bc901b874a21cafa2..2e201e50a64e9e45376d25b0f449c0814326c32c 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
 fn test<const N: usize, const M: usize>() -> [u8; M] {
     [0; N] //~ ERROR mismatched types
 }
diff --git a/src/test/ui/const-generics/generic-param-mismatch.stderr b/src/test/ui/const-generics/generic-param-mismatch.stderr
new file mode 100644 (file)
index 0000000..d0776d4
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/generic-param-mismatch.rs:2:5
+   |
+LL | fn test<const N: usize, const M: usize>() -> [u8; M] {
+   |                                              ------- expected `[u8; M]` because of return type
+LL |     [0; N]
+   |     ^^^^^^ expected `M`, found `N`
+   |
+   = note: expected array `[u8; M]`
+              found array `[u8; N]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr b/src/test/ui/const-generics/generic-sum-in-array-length.full.stderr
deleted file mode 100644 (file)
index c13882e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/generic-sum-in-array-length.rs:6:45
-   |
-LL | fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
-   |                                             ^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr b/src/test/ui/const-generics/generic-sum-in-array-length.min.stderr
deleted file mode 100644 (file)
index cff5a62..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/generic-sum-in-array-length.rs:6:53
-   |
-LL | fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
-   |                                                     ^ cannot perform const operation using `A`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `A`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/generic-sum-in-array-length.rs:6:57
-   |
-LL | fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
-   |                                                         ^ cannot perform const operation using `B`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `B`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/generic-sum-in-array-length.rs b/src/test/ui/const-generics/generic-sum-in-array-length.rs
deleted file mode 100644 (file)
index 7ee0394..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-fn foo<const A: usize, const B: usize>(bar: [usize; A + B]) {}
-//[min]~^ ERROR generic parameters may not be used in const operations
-//[min]~| ERROR generic parameters may not be used in const operations
-//[full]~^^^ ERROR constant expression depends on a generic parameter
-
-fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-1.rs
new file mode 100644 (file)
index 0000000..06f00de
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: u8>([u8; N as usize])
+where
+    [(); N as usize]:;
+
+struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 2) as usize]:;
+
+// unifying with subtrees
+struct Evaluatable<const N: u16>;
+fn foo<const N: u8>() where Evaluatable<{N as usize as u16 }>: {
+    let _ = Foo::<N>([1; N as usize]);
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.rs
new file mode 100644 (file)
index 0000000..3b5b87b
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Evaluatable<const N: u128> {}
+
+struct Foo<const N: u8>([u8; N as usize])
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
+where
+    Evaluatable<{N as u128}>:;
+
+struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
+
+struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
+//~^ Error: unconstrained generic constant
+//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-2.stderr
new file mode 100644 (file)
index 0000000..5ca04d2
--- /dev/null
@@ -0,0 +1,26 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:6:25
+   |
+LL | struct Foo<const N: u8>([u8; N as usize])
+   |                         ^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); N as usize]:`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:12:26
+   |
+LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-2.rs:16:25
+   |
+LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
+   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.rs
new file mode 100644 (file)
index 0000000..7561ae2
--- /dev/null
@@ -0,0 +1,47 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait {}
+pub struct EvaluatableU128<const N: u128>;
+
+struct HasCastInTraitImpl<const N: usize, const M: u128>;
+impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+
+pub fn use_trait_impl<const N: usize>()
+where
+    [(); { N + 1}]:,
+    EvaluatableU128<{N as u128}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    // errors are bad but seems to be pre-existing issue #86198
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+    //~^ Error: mismatched types
+    assert_impl::<HasCastInTraitImpl<14, 13>>();
+    //~^ Error: mismatched types
+}
+pub fn use_trait_impl_2<const N: usize>()
+where
+    [(); { N + 1}]:,
+    EvaluatableU128<{N as _}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    // errors are bad but seems to be pre-existing issue #86198
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+    //~^ Error: mismatched types
+    //~^^ Error: unconstrained generic constant
+    assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+    //~^ Error: mismatched types
+    assert_impl::<HasCastInTraitImpl<14, 13>>();
+    //~^ Error: mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
new file mode 100644 (file)
index 0000000..f235eb4
--- /dev/null
@@ -0,0 +1,147 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:17:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `use_trait_impl::assert_impl`
+  --> $DIR/abstract-const-as-cast-3.rs:14:23
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:17:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as u128 }`
+              found type `{ O as u128 }`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:20:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `use_trait_impl::assert_impl`
+  --> $DIR/abstract-const-as-cast-3.rs:14:23
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ^^^^^ required by this bound in `use_trait_impl::assert_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:20:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as _ }`
+              found type `{ O as u128 }`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:23:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
+   |
+   = note: expected type `12_u128`
+              found type `13_u128`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:25:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
+   |
+   = note: expected type `13_u128`
+              found type `14_u128`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:35:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `use_trait_impl_2::assert_impl`
+  --> $DIR/abstract-const-as-cast-3.rs:32:23
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:35:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as u128 }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as u128 }`
+              found type `{ O as u128 }`
+
+error: unconstrained generic constant
+  --> $DIR/abstract-const-as-cast-3.rs:38:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
+note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+  --> $DIR/abstract-const-as-cast-3.rs:8:22
+   |
+LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+   |                      ^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `use_trait_impl_2::assert_impl`
+  --> $DIR/abstract-const-as-cast-3.rs:32:23
+   |
+LL |     fn assert_impl<T: Trait>() {}
+   |                       ^^^^^ required by this bound in `use_trait_impl_2::assert_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:38:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ N as _ }`, found `{ O as u128 }`
+   |
+   = note: expected type `{ N as _ }`
+              found type `{ O as u128 }`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:41:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<13, { 12 as u128 }>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `12_u128`, found `13_u128`
+   |
+   = note: expected type `12_u128`
+              found type `13_u128`
+
+error[E0308]: mismatched types
+  --> $DIR/abstract-const-as-cast-3.rs:43:5
+   |
+LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `13_u128`, found `14_u128`
+   |
+   = note: expected type `13_u128`
+              found type `14_u128`
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-4.rs
new file mode 100644 (file)
index 0000000..184263f
--- /dev/null
@@ -0,0 +1,29 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait {}
+pub struct EvaluatableU128<const N: u128>;
+
+struct HasCastInTraitImpl<const N: usize, const M: u128>;
+impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
+
+pub fn use_trait_impl<const N: usize>() where EvaluatableU128<{N as u128}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
+    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<13, 13>>();
+}
+pub fn use_trait_impl_2<const N: usize>() where EvaluatableU128<{N as _}>:, {
+    fn assert_impl<T: Trait>() {}
+
+    assert_impl::<HasCastInTraitImpl<N, { N as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<N, { N as _ }>>();
+    assert_impl::<HasCastInTraitImpl<12, { 12 as u128 }>>();
+    assert_impl::<HasCastInTraitImpl<13, 13>>();
+}
+
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
new file mode 100644 (file)
index 0000000..deb6f3b
--- /dev/null
@@ -0,0 +1,18 @@
+error: unconstrained generic constant
+  --> $DIR/array-size-in-generic-struct-param.rs:8:38
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                      ^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); 0 + N]:`
+
+error: overly complex generic constant
+  --> $DIR/array-size-in-generic-struct-param.rs:19:15
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |               ^^^^^^^^^^^^ unsupported projection
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr
new file mode 100644 (file)
index 0000000..18e9135
--- /dev/null
@@ -0,0 +1,29 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/array-size-in-generic-struct-param.rs:8:48
+   |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+   |                                                ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/array-size-in-generic-struct-param.rs:19:15
+   |
+LL |     arr: [u8; CFG.arr_size],
+   |               ^^^ cannot perform const operation using `CFG`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `CFG`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: `Config` is forbidden as the type of a const generic parameter
+  --> $DIR/array-size-in-generic-struct-param.rs:17:21
+   |
+LL | struct B<const CFG: Config> {
+   |                     ^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.rs
new file mode 100644 (file)
index 0000000..7d3fe41
--- /dev/null
@@ -0,0 +1,29 @@
+// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`.
+// revisions: full min
+
+#![cfg_attr(full, feature(generic_const_exprs, adt_const_params))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+#[allow(dead_code)]
+struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+//[full]~^ ERROR unconstrained generic constant
+//[min]~^^ ERROR generic parameters may not be used in const operations
+
+#[derive(PartialEq, Eq)]
+struct Config {
+    arr_size: usize,
+}
+
+struct B<const CFG: Config> {
+    //[min]~^ ERROR `Config` is forbidden
+    arr: [u8; CFG.arr_size],
+    //[full]~^ ERROR overly complex generic constant
+    //[min]~^^ ERROR generic parameters may not be used in const operations
+}
+
+const C: Config = Config { arr_size: 5 };
+
+fn main() {
+    let b = B::<C> { arr: [1, 2, 3, 4, 5] };
+    assert_eq!(b.arr.len(), 5);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/associated-const.rs b/src/test/ui/const-generics/generic_const_exprs/associated-const.rs
new file mode 100644 (file)
index 0000000..a677763
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+struct Foo<T>(T);
+impl<T> Foo<T> {
+    const VALUE: usize = std::mem::size_of::<T>();
+}
+
+fn test<T>() {
+    let _ = [0; Foo::<u8>::VALUE];
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs b/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs
new file mode 100644 (file)
index 0000000..4d89f18
--- /dev/null
@@ -0,0 +1,31 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait BlockCipher {
+    const BLOCK_SIZE: usize;
+}
+
+struct FooCipher;
+impl BlockCipher for FooCipher {
+    const BLOCK_SIZE: usize = 64;
+}
+
+struct BarCipher;
+impl BlockCipher for BarCipher {
+    const BLOCK_SIZE: usize = 32;
+}
+
+pub struct Block<C>(C);
+
+pub fn test<C: BlockCipher, const M: usize>()
+where
+    [u8; M - C::BLOCK_SIZE]: Sized,
+{
+    let _ = [0; M - C::BLOCK_SIZE];
+}
+
+fn main() {
+    test::<FooCipher, 128>();
+    test::<BarCipher, 64>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs b/src/test/ui/const-generics/generic_const_exprs/auxiliary/const_evaluatable_lib.rs
new file mode 100644 (file)
index 0000000..15d618c
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+where
+    [u8; std::mem::size_of::<T>() - 1]: Sized,
+{
+    [0; std::mem::size_of::<T>() - 1]
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.rs b/src/test/ui/const-generics/generic_const_exprs/closures.rs
new file mode 100644 (file)
index 0000000..847843f
--- /dev/null
@@ -0,0 +1,6 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
+//~^ ERROR overly complex generic constant
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
new file mode 100644 (file)
index 0000000..9f0b725
--- /dev/null
@@ -0,0 +1,12 @@
+error: overly complex generic constant
+  --> $DIR/closures.rs:3:35
+   |
+LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
+   |                                   ^^^^-------^^
+   |                                       |
+   |                                       unsupported rvalue
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/cross_crate.rs b/src/test/ui/const-generics/generic_const_exprs/cross_crate.rs
new file mode 100644 (file)
index 0000000..dfc69e0
--- /dev/null
@@ -0,0 +1,15 @@
+// aux-build:const_evaluatable_lib.rs
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+extern crate const_evaluatable_lib;
+
+fn user<T>() where [u8; std::mem::size_of::<T>() - 1]: Sized {
+    assert_eq!(const_evaluatable_lib::test1::<T>(), [0; std::mem::size_of::<T>() - 1]);
+}
+
+fn main() {
+    assert_eq!(const_evaluatable_lib::test1::<u32>(), [0; 3]);
+    user::<u32>();
+    user::<u64>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs b/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.rs
new file mode 100644 (file)
index 0000000..b08fffd
--- /dev/null
@@ -0,0 +1,14 @@
+// aux-build:const_evaluatable_lib.rs
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+extern crate const_evaluatable_lib;
+
+fn user<T>() {
+    let _ = const_evaluatable_lib::test1::<T>();
+    //~^ ERROR unconstrained generic constant
+    //~| ERROR unconstrained generic constant
+    //~| ERROR unconstrained generic constant
+    //~| ERROR unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr b/src/test/ui/const-generics/generic_const_exprs/cross_crate_predicate.stderr
new file mode 100644 (file)
index 0000000..7b4d46b
--- /dev/null
@@ -0,0 +1,54 @@
+error: unconstrained generic constant
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
+note: required by a bound in `test1`
+  --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
+
+error: unconstrained generic constant
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
+note: required by a bound in `test1`
+  --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
+   |
+LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
+
+error: unconstrained generic constant
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
+note: required by a bound in `test1`
+  --> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
+
+error: unconstrained generic constant
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<T>() - 1]:`
+note: required by a bound in `test1`
+  --> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
+   |
+LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test1`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/different-fn.rs b/src/test/ui/const-generics/generic_const_exprs/different-fn.rs
new file mode 100644 (file)
index 0000000..e8bc703
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+use std::mem::size_of;
+use std::marker::PhantomData;
+
+struct Foo<T>(PhantomData<T>);
+
+fn test<T>() -> [u8; size_of::<T>()] {
+    [0; size_of::<Foo<T>>()]
+    //~^ ERROR unconstrained generic constant
+    //~| ERROR mismatched types
+}
+
+fn main() {
+    test::<u32>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr b/src/test/ui/const-generics/generic_const_exprs/different-fn.stderr
new file mode 100644 (file)
index 0000000..2aeb9b9
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/different-fn.rs:10:5
+   |
+LL |     [0; size_of::<Foo<T>>()]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ expected `size_of::<T>()`, found `size_of::<Foo<T>>()`
+   |
+   = note: expected type `size_of::<T>()`
+              found type `size_of::<Foo<T>>()`
+
+error: unconstrained generic constant
+  --> $DIR/different-fn.rs:10:9
+   |
+LL |     [0; size_of::<Foo<T>>()]
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); size_of::<Foo<T>>()]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/division.rs b/src/test/ui/const-generics/generic_const_exprs/division.rs
new file mode 100644 (file)
index 0000000..098fa9e
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn with_bound<const N: usize>() where [u8; N / 2]: Sized {
+    let _: [u8; N / 2] = [0; N / 2];
+}
+
+fn main() {
+    with_bound::<4>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs b/src/test/ui/const-generics/generic_const_exprs/dont-eagerly-error-in-is-const-evaluatable.rs
new file mode 100644 (file)
index 0000000..3543960
--- /dev/null
@@ -0,0 +1,16 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// This test is a repro for #82279. It checks that we don't error
+// when calling is_const_evaluatable on `std::mem::size_of::<T>()`
+// when looking for candidates that may prove `T: Foo` in `foo`
+
+trait Foo {}
+
+#[allow(dead_code)]
+fn foo<T: Foo>() {}
+
+impl<T> Foo for T where [(); std::mem::size_of::<T>()]:  {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/drop_impl.rs b/src/test/ui/const-generics/generic_const_exprs/drop_impl.rs
new file mode 100644 (file)
index 0000000..077f77a
--- /dev/null
@@ -0,0 +1,16 @@
+//check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>
+where
+    [(); N + 1]: ;
+
+impl<const N: usize> Drop for Foo<N>
+where
+    [(); N + 1]: ,
+{
+    fn drop(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs b/src/test/ui/const-generics/generic_const_exprs/elaborate-trait-pred.rs
new file mode 100644 (file)
index 0000000..e411115
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+// Test that we use the elaborated predicates from traits
+// to satisfy const evaluatable predicates.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+use std::mem::size_of;
+
+trait Foo: Sized
+where
+    [(); size_of::<Self>()]: Sized,
+{
+}
+
+impl Foo for u64 {}
+impl Foo for u32 {}
+
+fn foo<T: Foo>() -> [u8; size_of::<T>()] {
+    [0; size_of::<T>()]
+}
+
+fn main() {
+    assert_eq!(foo::<u32>(), [0; 4]);
+    assert_eq!(foo::<u64>(), [0; 8]);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.rs
new file mode 100644 (file)
index 0000000..80d0662
--- /dev/null
@@ -0,0 +1,31 @@
+#![crate_type = "lib"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub struct Const<const U: u8>;
+
+pub trait Trait {
+    type AssocTy;
+    fn assoc_fn() -> Self::AssocTy;
+}
+
+impl<const U: u8> Trait for Const<U>
+//~^ WARN private type
+//~| WARN this was previously
+//~| WARN private type
+//~| WARN this was previously
+
+where
+    Const<{ my_const_fn(U) }>: ,
+{
+    type AssocTy = Const<{ my_const_fn(U) }>;
+    //~^ ERROR private type
+    fn assoc_fn() -> Self::AssocTy {
+        Const
+    }
+}
+
+const fn my_const_fn(val: u8) -> u8 {
+    // body of this function doesn't matter
+    val
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-privacy.stderr
new file mode 100644 (file)
index 0000000..842c22c
--- /dev/null
@@ -0,0 +1,43 @@
+warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
+  --> $DIR/eval-privacy.rs:12:1
+   |
+LL | / impl<const U: u8> Trait for Const<U>
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `#[warn(private_in_public)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+warning: private type `fn(u8) -> u8 {my_const_fn}` in public interface (error E0446)
+  --> $DIR/eval-privacy.rs:12:1
+   |
+LL | / impl<const U: u8> Trait for Const<U>
+LL | |
+LL | |
+LL | |
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+
+error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface
+  --> $DIR/eval-privacy.rs:21:5
+   |
+LL |     type AssocTy = Const<{ my_const_fn(U) }>;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type
+...
+LL | const fn my_const_fn(val: u8) -> u8 {
+   | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private
+
+error: aborting due to previous error; 2 warnings emitted
+
+For more information about this error, try `rustc --explain E0446`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs b/src/test/ui/const-generics/generic_const_exprs/evaluated-to-ambig.rs
new file mode 100644 (file)
index 0000000..340e35e
--- /dev/null
@@ -0,0 +1,22 @@
+// check-pass
+
+// We previously always returned ambiguity when equating generic consts, even if they
+// only contain generic parameters. This is incorrect as trying to unify `N > 1` with `M > 1`
+// should fail.
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+enum Assert<const COND: bool> {}
+trait IsTrue {}
+impl IsTrue for Assert<true> {}
+
+struct Foo<const N: usize, const M: usize>;
+trait Bar<const N: usize, const M: usize> {}
+impl<const N: usize, const M: usize> Bar<N, M> for Foo<N, M>
+where
+    Assert<{ N > 1 }>: IsTrue,
+    Assert<{ M > 1 }>: IsTrue,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs b/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.rs
new file mode 100644 (file)
index 0000000..10ab2fd
--- /dev/null
@@ -0,0 +1,11 @@
+type Arr<const N: usize> = [u8; N - 1];
+//~^ ERROR generic parameters may not be used in const operations
+
+fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+    Default::default()
+}
+
+fn main() {
+    let x = test::<33>();
+    assert_eq!(x, [0; 32]);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/src/test/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr
new file mode 100644 (file)
index 0000000..2d60eba
--- /dev/null
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/feature-gate-generic_const_exprs.rs:1:33
+   |
+LL | type Arr<const N: usize> = [u8; N - 1];
+   |                                 ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/fn_call.rs b/src/test/ui/const-generics/generic_const_exprs/fn_call.rs
new file mode 100644 (file)
index 0000000..cbe4277
--- /dev/null
@@ -0,0 +1,30 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+const fn test_me<T>(a: usize, b: usize) -> usize {
+    if a < b {
+        std::mem::size_of::<T>()
+    } else {
+        usize::MAX
+    }
+}
+
+fn test_simple<T>() -> [u8; std::mem::size_of::<T>()]
+where
+    [u8; std::mem::size_of::<T>()]: Sized,
+{
+    [0; std::mem::size_of::<T>()]
+}
+
+fn test_with_args<T, const N: usize>() -> [u8; test_me::<T>(N, N + 1) + N]
+where
+    [u8; test_me::<T>(N, N + 1) + N]: Sized,
+{
+    [0; test_me::<T>(N, N + 1) + N]
+}
+
+fn main() {
+    assert_eq!([0; 8], test_simple::<u64>());
+    assert_eq!([0; 12], test_with_args::<u64, 4>());
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs
new file mode 100644 (file)
index 0000000..9095314
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn test<const N: usize>() -> [u8; N - 1] {
+    //~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed
+    todo!()
+}
+
+fn main() {
+    test::<0>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr
new file mode 100644 (file)
index 0000000..31ccf97
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed
+  --> $DIR/from-sig-fail.rs:4:35
+   |
+LL | fn test<const N: usize>() -> [u8; N - 1] {
+   |                                   ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig.rs
new file mode 100644 (file)
index 0000000..28de4f8
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ N > 10 }> {
+    Foo
+}
+
+fn main() {
+    let _: Foo<true> = test::<12>();
+    let _: Foo<false> = test::<9>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.rs b/src/test/ui/const-generics/generic_const_exprs/function-call.rs
new file mode 100644 (file)
index 0000000..b5de666
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+const fn foo<T>() -> usize {
+    // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here,
+    // which would cause this function to fail on 32 bit systems.
+    if false {
+        std::mem::size_of::<T>()
+    } else {
+        8
+    }
+}
+
+fn test<T>() {
+    let _ = [0; foo::<T>()];
+    //~^ WARN cannot use constants which depend on generic parameters in types
+    //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.stderr b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
new file mode 100644 (file)
index 0000000..0d84637
--- /dev/null
@@ -0,0 +1,12 @@
+warning: cannot use constants which depend on generic parameters in types
+  --> $DIR/function-call.rs:14:17
+   |
+LL |     let _ = [0; foo::<T>()];
+   |                 ^^^^^^^^^^
+   |
+   = note: `#[warn(const_evaluatable_unchecked)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/impl-bounds.rs b/src/test/ui/const-generics/generic_const_exprs/impl-bounds.rs
new file mode 100644 (file)
index 0000000..7120d6e
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+use std::mem::size_of;
+
+struct Foo<T, const N: usize>(T);
+
+impl<T> Foo<T, { size_of::<T>() }> {
+    fn test() {
+        let _: [u8; std::mem::size_of::<T>()];
+    }
+}
+
+trait Bar<const N: usize> {
+    fn test_me();
+}
+
+impl<T> Bar<{ size_of::<T>() }> for Foo<T, 3> {
+    fn test_me() {
+        let _: [u8; std::mem::size_of::<T>()];
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/infer-too-generic.rs b/src/test/ui/const-generics/generic_const_exprs/infer-too-generic.rs
new file mode 100644 (file)
index 0000000..b8058c2
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+use std::{mem, ptr};
+
+fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1])
+where
+    [T; N - 1]: Sized,
+{
+    let arr = mem::ManuallyDrop::new(arr);
+    unsafe {
+        let head = ptr::read(&arr[0]);
+        let tail = ptr::read(&arr[1..] as *const [T] as *const [T; N - 1]);
+        (head, tail)
+    }
+}
+
+fn main() {
+    let arr = [0, 1, 2, 3, 4];
+    let (head, tail) = split_first(arr);
+    assert_eq!(head, 0);
+    assert_eq!(tail, [1, 2, 3, 4]);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-62504.full.stderr
new file mode 100644 (file)
index 0000000..f2ae361
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-62504.rs:18:21
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                     ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+   |
+   = note: expected type `X`
+              found type `Self::SIZE`
+
+error: unconstrained generic constant
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); Self::SIZE]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-62504.min.stderr
new file mode 100644 (file)
index 0000000..5d45e30
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-62504.rs:18:21
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                     ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+   |
+   = note: expected array `[u32; X]`
+              found array `[u32; _]`
+
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-62504.rs:18:25
+   |
+LL |         ArrayHolder([0; Self::SIZE])
+   |                         ^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-62504.rs b/src/test/ui/const-generics/generic_const_exprs/issue-62504.rs
new file mode 100644 (file)
index 0000000..a97f4b8
--- /dev/null
@@ -0,0 +1,27 @@
+// revisions: full min
+#![allow(incomplete_features)]
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+trait HasSize {
+    const SIZE: usize;
+}
+
+impl<const X: usize> HasSize for ArrayHolder<X> {
+    const SIZE: usize = X;
+}
+
+struct ArrayHolder<const X: usize>([u32; X]);
+
+impl<const X: usize> ArrayHolder<X> {
+    pub const fn new() -> Self {
+        ArrayHolder([0; Self::SIZE])
+        //~^ ERROR mismatched types
+        //[full]~^^ ERROR unconstrained generic constant
+        //[min]~^^^ ERROR constant expression depends on a generic parameter
+    }
+}
+
+fn main() {
+    let mut array = ArrayHolder::new();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.rs b/src/test/ui/const-generics/generic_const_exprs/issue-69654.rs
new file mode 100644 (file)
index 0000000..9b36699
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Bar<T> {}
+impl<T> Bar<T> for [u8; T] {}
+//~^ ERROR expected value, found type parameter `T`
+
+struct Foo<const N: usize> {}
+impl<const N: usize> Foo<N>
+where
+    [u8; N]: Bar<[(); N]>,
+{
+    fn foo() {}
+}
+
+fn main() {
+    Foo::foo();
+    //~^ ERROR the function or associated item
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr
new file mode 100644 (file)
index 0000000..0ce7640
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0423]: expected value, found type parameter `T`
+  --> $DIR/issue-69654.rs:5:25
+   |
+LL | impl<T> Bar<T> for [u8; T] {}
+   |                         ^ not a value
+
+error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied
+  --> $DIR/issue-69654.rs:17:10
+   |
+LL | struct Foo<const N: usize> {}
+   | -------------------------- function or associated item `foo` not found for this
+...
+LL |     Foo::foo();
+   |          ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `[u8; _]: Bar<[(); _]>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0599.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72787.min.stderr
new file mode 100644 (file)
index 0000000..3c7a740
--- /dev/null
@@ -0,0 +1,65 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-72787.rs:11:17
+   |
+LL |     Condition<{ LHS <= RHS }>: True
+   |                 ^^^ cannot perform const operation using `LHS`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `LHS`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-72787.rs:11:24
+   |
+LL |     Condition<{ LHS <= RHS }>: True
+   |                        ^^^ cannot perform const operation using `RHS`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `RHS`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-72787.rs:25:25
+   |
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                         ^ cannot perform const operation using `I`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `I`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-72787.rs:25:36
+   |
+LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+   |                                    ^ cannot perform const operation using `J`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `J`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72787.rs:21:26
+   |
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
+   |
+   = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
+note: required by a bound in `True`
+  --> $DIR/issue-72787.rs:8:1
+   |
+LL | pub trait True {}
+   | ^^^^^^^^^^^^^^ required by this bound in `True`
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72787.rs:21:26
+   |
+LL |     IsLessOrEqual<I, 8>: True,
+   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
+   |
+   = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
+note: required by a bound in `True`
+  --> $DIR/issue-72787.rs:8:1
+   |
+LL | pub trait True {}
+   | ^^^^^^^^^^^^^^ required by this bound in `True`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72787.rs
new file mode 100644 (file)
index 0000000..77ad57f
--- /dev/null
@@ -0,0 +1,35 @@
+// [full] check-pass
+// revisions: full min
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+pub struct IsLessOrEqual<const LHS: u32, const RHS: u32>;
+pub struct Condition<const CONDITION: bool>;
+pub trait True {}
+
+impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
+    Condition<{ LHS <= RHS }>: True
+//[min]~^ Error generic parameters may not be used in const operations
+//[min]~| Error generic parameters may not be used in const operations
+{
+}
+impl True for Condition<true> {}
+
+struct S<const I: u32, const J: u32>;
+impl<const I: u32, const J: u32> S<I, J>
+where
+    IsLessOrEqual<I, 8>: True,
+//[min]~^ Error type annotations needed [E0283]
+//[min]~| Error type annotations needed [E0283]
+    IsLessOrEqual<J, 8>: True,
+    IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
+//[min]~^ Error generic parameters may not be used in const operations
+//[min]~| Error generic parameters may not be used in const operations
+    // Condition<{ 8 - I <= 8 - J }>: True,
+{
+    fn print() {
+        println!("I {} J {}", I, J);
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.full.stderr
new file mode 100644 (file)
index 0000000..d536f6f
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-72819-generic-in-const-eval.rs:20:12
+   |
+LL |     let x: Arr<{usize::MAX}> = Arr {};
+   |            ^^^^^^^^^^^^^^^^^ expected `false`, found `true`
+   |
+   = note: expected type `false`
+              found type `true`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-72819-generic-in-const-eval.rs:20:32
+   |
+LL |     let x: Arr<{usize::MAX}> = Arr {};
+   |                                ^^^ expected `false`, found `true`
+   |
+   = note: expected type `false`
+              found type `true`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr
new file mode 100644 (file)
index 0000000..4267141
--- /dev/null
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-72819-generic-in-const-eval.rs:8:17
+   |
+LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
+   |                 ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.rs
new file mode 100644 (file)
index 0000000..7a5aa9e
--- /dev/null
@@ -0,0 +1,23 @@
+// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type
+// bounds.
+// revisions: full min
+#![cfg_attr(full, feature(generic_const_exprs))]
+#![cfg_attr(full, allow(incomplete_features))]
+
+struct Arr<const N: usize>
+where Assert::<{N < usize::MAX / 2}>: IsTrue,
+//[min]~^ ERROR generic parameters may not be used in const operations
+{
+}
+
+enum Assert<const CHECK: bool> {}
+
+trait IsTrue {}
+
+impl IsTrue for Assert<true> {}
+
+fn main() {
+    let x: Arr<{usize::MAX}> = Arr {};
+    //[full]~^ ERROR mismatched types
+    //[full]~| ERROR mismatched types
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-73899.rs b/src/test/ui/const-generics/generic_const_exprs/issue-73899.rs
new file mode 100644 (file)
index 0000000..d1ab1be
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
+
+trait FooImpl<const IS_ZERO: bool> {}
+
+impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
+
+impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
+
+fn foo<T: Foo>(_v: T) {}
+
+fn main() {
+    foo([]);
+    foo([()]);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-74634.rs b/src/test/ui/const-generics/generic_const_exprs/issue-74634.rs
new file mode 100644 (file)
index 0000000..cd1f7a9
--- /dev/null
@@ -0,0 +1,28 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait If<const COND: bool> {}
+impl If<true> for () {}
+
+trait IsZero<const N: u8> {
+    type Answer;
+}
+
+struct True;
+struct False;
+
+impl<const N: u8> IsZero<N> for ()
+where (): If<{N == 0}> {
+    type Answer = True;
+}
+
+trait Foobar<const N: u8> {}
+
+impl<const N: u8> Foobar<N> for ()
+where (): IsZero<N, Answer = True> {}
+
+impl<const N: u8> Foobar<N> for ()
+where (): IsZero<N, Answer = False> {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs b/src/test/ui/const-generics/generic_const_exprs/issue-76595.rs
new file mode 100644 (file)
index 0000000..faa8b3d
--- /dev/null
@@ -0,0 +1,17 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Bool<const B: bool>;
+
+trait True {}
+
+impl True for Bool<true> {}
+
+fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
+    todo!()
+}
+
+fn main() {
+    test::<2>();
+    //~^ ERROR this function takes 2 generic arguments
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-76595.stderr
new file mode 100644 (file)
index 0000000..3b69a40
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/issue-76595.rs:15:5
+   |
+LL |     test::<2>();
+   |     ^^^^   - supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `T`, `P`
+  --> $DIR/issue-76595.rs:10:4
+   |
+LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
+   |    ^^^^ -        -
+help: add missing generic argument
+   |
+LL |     test::<2, P>();
+   |             +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.rs
new file mode 100644 (file)
index 0000000..2fa9a71
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// This test is a minimized reproduction for #79518 where
+// during error handling for the type mismatch we would try
+// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
+
+trait Foo {
+    type Assoc: PartialEq;
+    const AssocInstance: Self::Assoc;
+
+    fn foo()
+    where
+        [(); std::mem::size_of::<Self::Assoc>()]: ,
+    {
+        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+        //~^ Error: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
new file mode 100644 (file)
index 0000000..c90774e
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
+   |
+LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |
+   = note: expected associated type `<Self as Foo>::Assoc`
+                        found array `[(); _]`
+   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/generic_const_exprs/issue-80561-incorrect-param-env.rs
new file mode 100644 (file)
index 0000000..77d3c98
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// This tests that the correct `param_env` is used so that
+// attempting to normalize `Self::N` does not cause an ICE.
+
+pub struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+    pub fn foo() {}
+}
+
+pub trait Bar {
+    const N: usize;
+    fn bar()
+    where
+        [(); Self::N]: ,
+    {
+        Foo::<{ Self::N }>::foo();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs b/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs
new file mode 100644 (file)
index 0000000..275f699
--- /dev/null
@@ -0,0 +1,32 @@
+// check-fail
+
+// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place
+
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+use std::fmt::Debug;
+use std::marker::PhantomData;
+use std::mem::size_of;
+
+struct Inline<T>
+where
+    [u8; size_of::<T>() + 1]: ,
+{
+    _phantom: PhantomData<T>,
+    buf: [u8; size_of::<T>() + 1],
+}
+
+impl<T> Inline<T>
+where
+    [u8; size_of::<T>() + 1]: ,
+{
+    pub fn new(val: T) -> Inline<T> {
+        todo!()
+    }
+}
+
+fn main() {
+    let dst = Inline::<dyn Debug>::new(0); //~ ERROR
+    //~^ ERROR
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
new file mode 100644 (file)
index 0000000..56cb11b
--- /dev/null
@@ -0,0 +1,72 @@
+error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     size_of called on unsized type `dyn Debug`
+   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+  ::: $DIR/issue-80742.rs:22:10
+   |
+LL |     [u8; size_of::<T>() + 1]: ,
+   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:22:10
+
+error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied
+  --> $DIR/issue-80742.rs:30:36
+   |
+LL | / struct Inline<T>
+LL | | where
+LL | |     [u8; size_of::<T>() + 1]: ,
+LL | | {
+LL | |     _phantom: PhantomData<T>,
+LL | |     buf: [u8; size_of::<T>() + 1],
+LL | | }
+   | |_- function or associated item `new` not found for this
+...
+LL |       let dst = Inline::<dyn Debug>::new(0);
+   |                                      ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
+   |
+  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+   |
+LL |   pub trait Debug {
+   |   --------------- doesn't satisfy `dyn Debug: Sized`
+   |
+   = note: the following trait bounds were not satisfied:
+           `dyn Debug: Sized`
+
+error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     size_of called on unsized type `dyn Debug`
+   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+  ::: $DIR/issue-80742.rs:14:10
+   |
+LL |     [u8; size_of::<T>() + 1]: ,
+   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:14:10
+
+error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
+  --> $DIR/issue-80742.rs:30:15
+   |
+LL |     let dst = Inline::<dyn Debug>::new(0);
+   |               ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `dyn Debug`
+note: required by a bound in `Inline`
+  --> $DIR/issue-80742.rs:12:15
+   |
+LL | struct Inline<T>
+   |               ^ required by this bound in `Inline`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | struct Inline<T: ?Sized>
+   |                ++++++++
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0277, E0599.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-83765.rs b/src/test/ui/const-generics/generic_const_exprs/issue-83765.rs
new file mode 100644 (file)
index 0000000..fac811d
--- /dev/null
@@ -0,0 +1,38 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait TensorDimension {
+    const DIM: usize;
+}
+
+trait TensorSize: TensorDimension {
+    fn size(&self) -> [usize; Self::DIM];
+}
+
+trait Broadcastable: TensorSize + Sized {
+    type Element;
+    fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {}
+}
+
+struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
+    reference: &'a T,
+    closure: F,
+}
+
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
+    for BMap<'a, R, T, F, DIM>
+{
+    const DIM: usize = DIM;
+}
+impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
+    for BMap<'a, R, T, F, DIM>
+{
+    fn size(&self) -> [usize; DIM] {
+        //~^ ERROR: method not compatible with trait [E0308]
+        self.reference.size()
+        //~^ ERROR: unconstrained generic constant
+        //~| ERROR: mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-83765.stderr
new file mode 100644 (file)
index 0000000..ef785bf
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0308]: method not compatible with trait
+  --> $DIR/issue-83765.rs:30:5
+   |
+LL |     fn size(&self) -> [usize; DIM] {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
+   |
+   = note: expected type `Self::DIM`
+              found type `DIM`
+
+error: unconstrained generic constant
+  --> $DIR/issue-83765.rs:32:24
+   |
+LL |         self.reference.size()
+   |                        ^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-83765.rs:32:9
+   |
+LL |         self.reference.size()
+   |         ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
+   |
+   = note: expected type `DIM`
+              found type `Self::DIM`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-84408.rs b/src/test/ui/const-generics/generic_const_exprs/issue-84408.rs
new file mode 100644 (file)
index 0000000..fb2e559
--- /dev/null
@@ -0,0 +1,38 @@
+// Regression test for #84408.
+// check-pass
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Melon<const X: usize> {
+    fn new(arr: [i32; X]) -> Self;
+    fn change<T: Melon<X>>(self) -> T;
+}
+
+struct Foo([i32; 5]);
+struct Bar<const A: usize, const B: usize>([i32; A + B])
+where
+    [(); A + B]: ;
+
+impl Melon<5> for Foo {
+    fn new(arr: [i32; 5]) -> Self {
+        Foo(arr)
+    }
+    fn change<T: Melon<5>>(self) -> T {
+        T::new(self.0)
+    }
+}
+
+impl<const A: usize, const B: usize> Melon<{ A + B }> for Bar<A, B>
+where
+    [(); A + B]: ,
+{
+    fn new(arr: [i32; A + B]) -> Self {
+        Bar(arr)
+    }
+    fn change<T: Melon<{ A + B }>>(self) -> T {
+        T::new(self.0)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.rs b/src/test/ui/const-generics/generic_const_exprs/issue-85848.rs
new file mode 100644 (file)
index 0000000..771e68b
--- /dev/null
@@ -0,0 +1,31 @@
+#![feature(const_fn_trait_bound, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait _Contains<T> {
+    const does_contain: bool;
+}
+
+trait Contains<T, const Satisfied: bool> {}
+
+trait Delegates<T> {}
+
+impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+
+const fn contains<A, B>() -> bool
+where
+    A: _Contains<B>,
+{
+    A::does_contain
+}
+
+impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+
+fn writes_to_path<C>(cap: &C) {
+    writes_to_specific_path(&cap);
+    //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277]
+    //~| ERROR: unconstrained generic constant
+}
+
+fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
new file mode 100644 (file)
index 0000000..e51db35
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
+   |
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+note: required by a bound in `writes_to_specific_path`
+  --> $DIR/issue-85848.rs:29:31
+   |
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path`
+
+error: unconstrained generic constant
+  --> $DIR/issue-85848.rs:24:5
+   |
+LL |     writes_to_specific_path(&cap);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
+note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+  --> $DIR/issue-85848.rs:21:12
+   |
+LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
+note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+  --> $DIR/issue-85848.rs:12:12
+   |
+LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
+   |            ^^^^^^^^^^^^     ^
+note: required by a bound in `writes_to_specific_path`
+  --> $DIR/issue-85848.rs:29:31
+   |
+LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
+   |                               ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/less_than.rs b/src/test/ui/const-generics/generic_const_exprs/less_than.rs
new file mode 100644 (file)
index 0000000..2e9af1b
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ N > 10 }> where Foo<{ N > 10 }>: Sized {
+    Foo
+}
+
+fn main() {
+    let _: Foo<true> = test::<12>();
+    let _: Foo<false> = test::<9>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.rs b/src/test/ui/const-generics/generic_const_exprs/let-bindings.rs
new file mode 100644 (file)
index 0000000..cd5d76d
--- /dev/null
@@ -0,0 +1,15 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+// We do not yet want to support let-bindings in abstract consts,
+// so this test should keep failing for now.
+fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+    //~^ ERROR overly complex generic constant
+    //~| ERROR overly complex generic constant
+    Default::default()
+}
+
+fn main() {
+    let x = test::<31>();
+    assert_eq!(x, [0; 32]);
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
new file mode 100644 (file)
index 0000000..5749def
--- /dev/null
@@ -0,0 +1,22 @@
+error: overly complex generic constant
+  --> $DIR/let-bindings.rs:6:68
+   |
+LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+   |                                                                    ^^^^^^-^^^^^^^^^^^^^
+   |                                                                          |
+   |                                                                          unsupported statement
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: overly complex generic constant
+  --> $DIR/let-bindings.rs:6:35
+   |
+LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
+   |                                   ^^^^^^-^^^^^^^^^^^^^
+   |                                         |
+   |                                         unsupported statement
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.rs b/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.rs
new file mode 100644 (file)
index 0000000..2bd3c80
--- /dev/null
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+const fn complex_maths<T>(n : usize) -> usize {
+  2 * n + 1
+}
+
+struct Example<T, const N: usize> {
+  a: [f32; N],
+  b: [f32; complex_maths::<T>(N)],
+  //~^ ERROR unconstrained
+  c: T,
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.stderr b/src/test/ui/const-generics/generic_const_exprs/needs_where_clause.stderr
new file mode 100644 (file)
index 0000000..7b41e39
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/needs_where_clause.rs:11:6
+   |
+LL |   b: [f32; complex_maths::<T>(N)],
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs b/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-1.rs
new file mode 100644 (file)
index 0000000..7e50228
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn callee<const M2: usize>() -> usize
+where
+    [u8; M2 + 1]: Sized,
+{
+    M2
+}
+
+fn caller<const N1: usize>() -> usize
+where
+    [u8; N1 + 1]: Sized,
+    [u8; (N1 + 1) + 1]: Sized,
+{
+    callee::<{ N1 + 1 }>()
+}
+
+fn main() {
+    assert_eq!(caller::<4>(), 5);
+}
+
+// Test that the ``(N1 + 1) + 1`` bound on ``caller`` satisfies the ``M2 + 1`` bound on ``callee``
diff --git a/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs b/src/test/ui/const-generics/generic_const_exprs/nested-abstract-consts-2.rs
new file mode 100644 (file)
index 0000000..769e3ae
--- /dev/null
@@ -0,0 +1,35 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Generic<const K: u64>;
+
+struct ConstU64<const K: u64>;
+
+impl<const K: u64> Generic<K>
+where
+    ConstU64<{ K - 1 }>: ,
+{
+    fn foo(self) -> u64 {
+        K
+    }
+}
+
+impl<const K: u64> Generic<K>
+where
+    ConstU64<{ K - 1 }>: ,
+    ConstU64<{ K + 1 }>: ,
+    ConstU64<{ K + 1 - 1 }>: ,
+{
+    fn bar(self) -> u64 {
+        let x: Generic<{ K + 1 }> = Generic;
+        x.foo()
+    }
+}
+
+fn main() {
+    assert_eq!((Generic::<10>).bar(), 11);
+}
+
+// Test that the ``ConstU64<{ K + 1 - 1}>`` bound on ``bar``'s impl block satisfies the
+// ``ConstU64<{K - 1}>`` bound on ``foo``'s impl block
diff --git a/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs b/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-1.rs
new file mode 100644 (file)
index 0000000..316887e
--- /dev/null
@@ -0,0 +1,34 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn zero_init<const N: usize>() -> Substs1<N>
+where
+    [u8; N + 1]: ,
+{
+    Substs1([0; N + 1])
+}
+struct Substs1<const N: usize>([u8; N + 1])
+where
+    [(); N + 1]: ;
+
+fn substs2<const M: usize>() -> Substs1<{ M * 2 }>
+where
+    [(); { M * 2 } + 1]: ,
+{
+    zero_init::<{ M * 2 }>()
+}
+
+fn substs3<const L: usize>() -> Substs1<{ (L - 1) * 2 }>
+where
+    [(); (L - 1) * 2 + 1]: ,
+{
+    substs2::<{ L - 1 }>()
+}
+
+fn main() {
+    assert_eq!(substs3::<2>().0, [0; 3]);
+}
+
+// Test that the ``{ (L - 1) * 2 + 1 }`` bound on ``substs3`` satisfies the
+// ``{ N + 1 }`` bound on ``Substs1``
diff --git a/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs b/src/test/ui/const-generics/generic_const_exprs/nested_uneval_unification-2.rs
new file mode 100644 (file)
index 0000000..d45a646
--- /dev/null
@@ -0,0 +1,29 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused_parens, unused_braces)]
+
+fn zero_init<const N: usize>() -> Substs1<{ (N) }>
+where
+    [u8; { (N) }]: ,
+{
+    Substs1([0; { (N) }])
+}
+
+struct Substs1<const N: usize>([u8; { (N) }])
+where
+    [(); { (N) }]: ;
+
+fn substs2<const M: usize>() -> Substs1<{ (M) }> {
+    zero_init::<{ (M) }>()
+}
+
+fn substs3<const L: usize>() -> Substs1<{ (L) }> {
+    substs2::<{ (L) }>()
+}
+
+fn main() {
+    assert_eq!(substs3::<2>().0, [0; 2]);
+}
+
+// Test that the implicit ``{ (L) }`` bound on ``substs3`` satisfies the
+// ``{ (N) }`` bound on ``Substs1``
diff --git a/src/test/ui/const-generics/generic_const_exprs/no_where_clause.rs b/src/test/ui/const-generics/generic_const_exprs/no_where_clause.rs
new file mode 100644 (file)
index 0000000..9c5de03
--- /dev/null
@@ -0,0 +1,29 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features, unused)]
+
+const fn complex_maths(n : usize) -> usize {
+  2 * n + 1
+}
+
+pub struct Example<const N: usize> {
+  a: [f32; N],
+  b: [f32; complex_maths(N)],
+  //~^ ERROR unconstrained generic
+}
+
+impl<const N: usize> Example<N> {
+  pub fn new() -> Self {
+    Self {
+      a: [0.; N],
+      b: [0.; complex_maths(N)],
+    }
+  }
+}
+
+impl Example<2> {
+  pub fn sum(&self) -> f32 {
+    self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>()
+  }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/no_where_clause.stderr b/src/test/ui/const-generics/generic_const_exprs/no_where_clause.stderr
new file mode 100644 (file)
index 0000000..3e5c2f5
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/no_where_clause.rs:10:6
+   |
+LL |   b: [f32; complex_maths(N)],
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.rs
new file mode 100644 (file)
index 0000000..24d333a
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+
+const fn bar<T: ?Sized>() -> usize { 7 }
+
+trait Foo {
+    fn test(&self) -> [u8; bar::<Self>()];
+}
+
+impl Foo for () {
+    fn test(&self) -> [u8; bar::<Self>()] {
+        [0; bar::<Self>()]
+    }
+}
+
+fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object
+    v.test();
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
new file mode 100644 (file)
index 0000000..319e6c2
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-err-ret.rs:17:16
+   |
+LL | fn use_dyn(v: &dyn Foo) {
+   |                ^^^^^^^ `Foo` cannot be made into an object
+   |
+   = help: consider moving `test` to another trait
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety-err-ret.rs:8:23
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn test(&self) -> [u8; bar::<Self>()];
+   |                       ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.rs
new file mode 100644 (file)
index 0000000..42c1cc5
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+#![deny(where_clauses_object_safety)]
+
+
+const fn bar<T: ?Sized>() -> usize { 7 }
+
+trait Foo {
+    fn test(&self) where [u8; bar::<Self>()]: Sized;
+    //~^ ERROR the trait `Foo` cannot be made into an object
+    //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+impl Foo for () {
+    fn test(&self) where [u8; bar::<Self>()]: Sized {}
+}
+
+fn use_dyn(v: &dyn Foo) {
+    v.test();
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
new file mode 100644 (file)
index 0000000..45c7d83
--- /dev/null
@@ -0,0 +1,24 @@
+error: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety-err-where-bounds.rs:9:8
+   |
+LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
+   |        ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/object-safety-err-where-bounds.rs:3:9
+   |
+LL | #![deny(where_clauses_object_safety)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety-err-where-bounds.rs:9:8
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn test(&self) where [u8; bar::<Self>()]: Sized;
+   |        ^^^^ ...because method `test` references the `Self` type in its `where` clause
+   = help: consider moving `test` to another trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.rs
new file mode 100644 (file)
index 0000000..c6c196d
--- /dev/null
@@ -0,0 +1,22 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Foo<const N: usize> {
+    fn test(&self) -> [u8; N + 1];
+}
+
+impl<const N: usize> Foo<N> for () {
+    fn test(&self) -> [u8; N + 1] {
+        [0; N + 1]
+    }
+}
+
+fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
+    assert_eq!(v.test(), [0; N + 1]);
+}
+
+fn main() {
+    // FIXME(generic_const_exprs): Improve the error message here.
+    use_dyn(&());
+    //~^ ERROR type annotations needed
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok-infer-err.stderr
new file mode 100644 (file)
index 0000000..ce75314
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0284]: type annotations needed: cannot satisfy `the constant `use_dyn::<{_: usize}>::{constant#0}` can be evaluated`
+  --> $DIR/object-safety-ok-infer-err.rs:20:5
+   |
+LL |     use_dyn(&());
+   |     ^^^^^^^ cannot satisfy `the constant `use_dyn::<{_: usize}>::{constant#0}` can be evaluated`
+   |
+note: required by a bound in `use_dyn`
+  --> $DIR/object-safety-ok-infer-err.rs:14:55
+   |
+LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
+   |                                                       ^^^^^ required by this bound in `use_dyn`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-ok.rs b/src/test/ui/const-generics/generic_const_exprs/object-safety-ok.rs
new file mode 100644 (file)
index 0000000..f4c89f6
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Foo<const N: usize> {
+    fn test(&self) -> [u8; N + 1];
+}
+
+impl<const N: usize> Foo<N> for () {
+    fn test(&self) -> [u8; N + 1] {
+        [0; N + 1]
+    }
+}
+
+fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
+    assert_eq!(v.test(), [0; N + 1]);
+}
+
+fn main() {
+    use_dyn::<3>(&());
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs
new file mode 100644 (file)
index 0000000..c47a350
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+type Arr<const N: usize> = [u8; N - 1];
+//~^ ERROR evaluation of `Arr::<0_usize>::{constant#0}` failed
+
+fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized {
+//~^ ERROR evaluation of `test::<0_usize>::{constant#0}` failed
+    todo!()
+}
+
+fn main() {
+    test::<0>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr
new file mode 100644 (file)
index 0000000..99fc92f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed
+  --> $DIR/simple_fail.rs:7:48
+   |
+LL | fn test<const N: usize>() -> Arr<N> where [u8; N - 1]: Sized {
+   |                                                ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error[E0080]: evaluation of `Arr::<0_usize>::{constant#0}` failed
+  --> $DIR/simple_fail.rs:4:33
+   |
+LL | type Arr<const N: usize> = [u8; N - 1];
+   |                                 ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs b/src/test/ui/const-generics/generic_const_exprs/subexprs_are_const_evalutable.rs
new file mode 100644 (file)
index 0000000..d6574a3
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn make_array<const M: usize>() -> [(); M + 1] {
+    [(); M + 1]
+}
+
+fn foo<const N: usize>() -> [(); (N * 2) + 1] {
+    make_array::<{ N * 2 }>()
+}
+
+fn main() {
+    assert_eq!(foo::<10>(), [(); 10 * 2 + 1])
+}
+
+// Tests that N * 2 is considered const_evalutable by appearing as part of the (N * 2) + 1 const
diff --git a/src/test/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs b/src/test/ui/const-generics/generic_const_exprs/ty-alias-substitution.rs
new file mode 100644 (file)
index 0000000..d058b36
--- /dev/null
@@ -0,0 +1,14 @@
+// check-pass
+// Test that we correctly substitute generic arguments for type aliases.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+type Alias<T, const N: usize> = [T; N + 1];
+
+fn foo<const M: usize>() -> Alias<u32, M>  where [u8; M + 1]: Sized {
+    [0; M + 1]
+}
+
+fn main() {
+    foo::<0>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unop.rs b/src/test/ui/const-generics/generic_const_exprs/unop.rs
new file mode 100644 (file)
index 0000000..c12fef0
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ !(N > 10) }> where Foo<{ !(N > 10) }>: Sized {
+    Foo
+}
+
+fn main() {
+    let _: Foo<false> = test::<12>();
+    let _: Foo<true> = test::<9>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs b/src/test/ui/const-generics/generic_const_exprs/unused-complex-default-expr.rs
new file mode 100644 (file)
index 0000000..67fefd0
--- /dev/null
@@ -0,0 +1,6 @@
+// check-pass
+#![feature(generic_const_exprs, const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+struct Bar<const N: usize>(Foo<N, 3>);
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.rs b/src/test/ui/const-generics/generic_const_exprs/unused_expr.rs
new file mode 100644 (file)
index 0000000..c1bf19e
--- /dev/null
@@ -0,0 +1,25 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
+    //~^ ERROR overly complex generic constant
+    todo!()
+}
+
+fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
+    //~^ ERROR overly complex generic constant
+    todo!()
+}
+
+const fn foo(n: usize) {}
+
+fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
+    //~^ ERROR overly complex generic constant
+    todo!()
+}
+
+fn main() {
+    add::<12>();
+    div::<9>();
+    fn_call::<14>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
new file mode 100644 (file)
index 0000000..1687dbb
--- /dev/null
@@ -0,0 +1,32 @@
+error: overly complex generic constant
+  --> $DIR/unused_expr.rs:4:34
+   |
+LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
+   |                                  ^^-----^^^^^
+   |                                    |
+   |                                    dead code
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: overly complex generic constant
+  --> $DIR/unused_expr.rs:9:34
+   |
+LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
+   |                                  ^^-----^^^^^
+   |                                    |
+   |                                    dead code
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: overly complex generic constant
+  --> $DIR/unused_expr.rs:16:38
+   |
+LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
+   |                                      ^^------^^^^^
+   |                                        |
+   |                                        dead code
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to 3 previous errors
+
index 1aa22698b640502743cf6468da577e0164bbc2d8..7eb2c6a51fcfbffa69a1505af87ec38e70f0dfdc 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct S<const X: u32>;
 
 impl<const X: u32> S<X> {
diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.full.stderr
deleted file mode 100644 (file)
index ebc8f45..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/impl-trait-with-const-arguments.rs:23:20
-   |
-LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
-   |                    ^^^^^^ explicit generic argument not allowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.min.stderr
deleted file mode 100644 (file)
index ebc8f45..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
-  --> $DIR/impl-trait-with-const-arguments.rs:23:20
-   |
-LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
-   |                    ^^^^^^ explicit generic argument not allowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0632`.
index 2e6e49b9c0aa4fd99fcb19c4d9256f8a29a8b07b..24ba393c17f2a03ee48fc505644e8e4b01621e55 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
 trait Usizer {
     fn m(self) -> usize;
 }
diff --git a/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr b/src/test/ui/const-generics/impl-trait-with-const-arguments.stderr
new file mode 100644 (file)
index 0000000..6268a56
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
+  --> $DIR/impl-trait-with-const-arguments.rs:18:20
+   |
+LL |     assert_eq!(f::<4usize>(Usizable), 20usize);
+   |                    ^^^^^^ explicit generic argument not allowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0632`.
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.full.stderr
deleted file mode 100644 (file)
index 7a12f3b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
-  --> $DIR/incorrect-number-of-const-args.rs:11:5
-   |
-LL |     foo::<0>();
-   |     ^^^   - supplied 1 generic argument
-   |     |
-   |     expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `X`, `Y`
-  --> $DIR/incorrect-number-of-const-args.rs:6:4
-   |
-LL | fn foo<const X: usize, const Y: usize>() -> usize {
-   |    ^^^       -               -
-help: add missing generic argument
-   |
-LL |     foo::<0, Y>();
-   |            +++
-
-error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied
-  --> $DIR/incorrect-number-of-const-args.rs:14:5
-   |
-LL |     foo::<0, 0, 0>();
-   |     ^^^         - help: remove this generic argument
-   |     |
-   |     expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `X`, `Y`
-  --> $DIR/incorrect-number-of-const-args.rs:6:4
-   |
-LL | fn foo<const X: usize, const Y: usize>() -> usize {
-   |    ^^^       -               -
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.min.stderr
deleted file mode 100644 (file)
index 7a12f3b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
-  --> $DIR/incorrect-number-of-const-args.rs:11:5
-   |
-LL |     foo::<0>();
-   |     ^^^   - supplied 1 generic argument
-   |     |
-   |     expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `X`, `Y`
-  --> $DIR/incorrect-number-of-const-args.rs:6:4
-   |
-LL | fn foo<const X: usize, const Y: usize>() -> usize {
-   |    ^^^       -               -
-help: add missing generic argument
-   |
-LL |     foo::<0, Y>();
-   |            +++
-
-error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied
-  --> $DIR/incorrect-number-of-const-args.rs:14:5
-   |
-LL |     foo::<0, 0, 0>();
-   |     ^^^         - help: remove this generic argument
-   |     |
-   |     expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `X`, `Y`
-  --> $DIR/incorrect-number-of-const-args.rs:6:4
-   |
-LL | fn foo<const X: usize, const Y: usize>() -> usize {
-   |    ^^^       -               -
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0107`.
index 305559d93fdad20169ba87e80912eeff8df725c1..de2d126afd75a1bc9e057ff68cf465a207870fdf 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn foo<const X: usize, const Y: usize>() -> usize {
     0
 }
diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr
new file mode 100644 (file)
index 0000000..bf873da
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/incorrect-number-of-const-args.rs:6:5
+   |
+LL |     foo::<0>();
+   |     ^^^   - supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:1:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+help: add missing generic argument
+   |
+LL |     foo::<0, Y>();
+   |            +++
+
+error[E0107]: this function takes 2 generic arguments but 3 generic arguments were supplied
+  --> $DIR/incorrect-number-of-const-args.rs:9:5
+   |
+LL |     foo::<0, 0, 0>();
+   |     ^^^         - help: remove this generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `X`, `Y`
+  --> $DIR/incorrect-number-of-const-args.rs:1:4
+   |
+LL | fn foo<const X: usize, const Y: usize>() -> usize {
+   |    ^^^       -               -
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.full.stderr
deleted file mode 100644 (file)
index 01fb137..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-const-args.rs:11:5
-   |
-LL |     foo();
-   |     ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     foo::<X>();
-   |     ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.min.stderr
deleted file mode 100644 (file)
index 01fb137..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-const-args.rs:11:5
-   |
-LL |     foo();
-   |     ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     foo::<X>();
-   |     ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
index cc52892bd04b77be911dcecbb19fc4236136f419..f85a72910aff151b769aafbc5eb42d5dfaec2955 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn foo<const X: usize>() -> usize {
     0
 }
diff --git a/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr b/src/test/ui/const-generics/infer/cannot-infer-const-args.stderr
new file mode 100644 (file)
index 0000000..828f497
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/cannot-infer-const-args.rs:6:5
+   |
+LL |     foo();
+   |     ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     foo::<X>();
+   |     ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.full.stderr b/src/test/ui/const-generics/infer/method-chain.full.stderr
deleted file mode 100644 (file)
index 979d50b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/method-chain.rs:20:33
-   |
-LL |     Foo.bar().bar().bar().bar().baz();
-   |                                 ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
-   |
-help: consider specifying the const argument
-   |
-LL |     Foo.bar().bar().bar().bar().baz::<N>();
-   |                                 ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/method-chain.min.stderr b/src/test/ui/const-generics/infer/method-chain.min.stderr
deleted file mode 100644 (file)
index 979d50b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/method-chain.rs:20:33
-   |
-LL |     Foo.bar().bar().bar().bar().baz();
-   |                                 ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
-   |
-help: consider specifying the const argument
-   |
-LL |     Foo.bar().bar().bar().bar().baz::<N>();
-   |                                 ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
index 8ac6a7d6267b7bc8f9920567fec682eaece488ba..0c5eed4894cb37ad44be8dbc6d79c694f5c85e49 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct Foo;
 
 impl Foo {
diff --git a/src/test/ui/const-generics/infer/method-chain.stderr b/src/test/ui/const-generics/infer/method-chain.stderr
new file mode 100644 (file)
index 0000000..53d92e5
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/method-chain.rs:15:33
+   |
+LL |     Foo.bar().bar().bar().bar().baz();
+   |                                 ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.bar().bar().bar().bar().baz::<N>();
+   |                                 ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.full.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.full.stderr
deleted file mode 100644 (file)
index 31b7fc7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/one-param-uninferred.rs:15:23
-   |
-LL |     let _: [u8; 17] = foo();
-   |                       ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     let _: [u8; 17] = foo::<M>();
-   |                       ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.min.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.min.stderr
deleted file mode 100644 (file)
index 31b7fc7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/one-param-uninferred.rs:15:23
-   |
-LL |     let _: [u8; 17] = foo();
-   |                       ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     let _: [u8; 17] = foo::<M>();
-   |                       ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
index 0e947131f4cdb4deca473e66279a6f400eec98da..d6018650f533d5f95bd63de239938155f75498d2 100644 (file)
@@ -1,10 +1,4 @@
 // Test that we emit an error if we cannot properly infer a constant.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(min, feature(min_const_generics))]
-
 fn foo<const N: usize, const M: usize>() -> [u8; N] {
     todo!()
 }
diff --git a/src/test/ui/const-generics/infer/one-param-uninferred.stderr b/src/test/ui/const-generics/infer/one-param-uninferred.stderr
new file mode 100644 (file)
index 0000000..acf5917
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/one-param-uninferred.rs:9:23
+   |
+LL |     let _: [u8; 17] = foo();
+   |                       ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     let _: [u8; 17] = foo::<M>();
+   |                       ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.full.stderr b/src/test/ui/const-generics/infer/uninferred-consts.full.stderr
deleted file mode 100644 (file)
index bee4b69..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:13:9
-   |
-LL |     Foo.foo();
-   |         ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     Foo.foo::<A>();
-   |         ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.min.stderr b/src/test/ui/const-generics/infer/uninferred-consts.min.stderr
deleted file mode 100644 (file)
index bee4b69..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/uninferred-consts.rs:13:9
-   |
-LL |     Foo.foo();
-   |         ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
-   |
-help: consider specifying the const argument
-   |
-LL |     Foo.foo::<A>();
-   |         ~~~~~~~~
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
index bcd9aadb78af9f0692c1e9702ff0b976289570ee..657f4b513042cba5514336c6b77c062485dbbc2a 100644 (file)
@@ -1,8 +1,4 @@
 // Test that we emit an error if we cannot properly infer a constant.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 // taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
 struct Foo;
diff --git a/src/test/ui/const-generics/infer/uninferred-consts.stderr b/src/test/ui/const-generics/infer/uninferred-consts.stderr
new file mode 100644 (file)
index 0000000..a6c79fc
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/uninferred-consts.rs:9:9
+   |
+LL |     Foo.foo();
+   |         ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
+   |
+help: consider specifying the const argument
+   |
+LL |     Foo.foo::<A>();
+   |         ~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
index 5e2a3eaff5438ec8c51d7e4dda912679f54d4682..10317a1b98fcc2a980ceebd79a154b14cc7ea693 100644 (file)
@@ -1,10 +1,6 @@
 // run-pass
 //
 // see issue #70529
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: usize> {
     arr: [u8; N],
index 0273383856fd97dedaba45817d7f0e9e89f657a2..40f6f5b8d55cef999c06296eb7f19f8445672024 100644 (file)
@@ -1,10 +1,6 @@
 // check-pass
 //
 // see issue #70529
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 fn as_chunks<const N: usize>() -> [u8; N] {
     loop {}
index 96e5976e44b336b3954e1a84dc19872822cc1ea5..2b8731ba7096c09574e9eb8839850dca39778273 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) {
     f([1, 2, 3]);
diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.full.stderr
deleted file mode 100644 (file)
index 3e90dbe..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/intrinsics-type_name-as-const-argument.rs:14:8
-   |
-LL |     T: Trait<{std::intrinsics::type_name::<T>()}>
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
index 8701d54f5c963d19918abab2f4b800a279cb6740..b8a1027c9ebdb0a5b0f1c3d65c28a271058ce80f 100644 (file)
@@ -1,20 +1,20 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/intrinsics-type_name-as-const-argument.rs:14:44
+  --> $DIR/intrinsics-type_name-as-const-argument.rs:15:44
    |
 LL |     T: Trait<{std::intrinsics::type_name::<T>()}>
    |                                            ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/intrinsics-type_name-as-const-argument.rs:9:22
+  --> $DIR/intrinsics-type_name-as-const-argument.rs:10:22
    |
 LL | trait Trait<const S: &'static str> {}
    |                      ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index f24dd42eb2da7bc5690956b1b57670ba05082899..147a00cb26bfc55b7d8d288bc95e2f962bcb083d 100644 (file)
@@ -1,7 +1,8 @@
+// [full] check-pass
 // revisions: full min
 
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params, generic_const_exprs))]
 
 #![feature(core_intrinsics)]
 #![feature(const_type_name)]
@@ -13,7 +14,6 @@ struct Bug<T>
 where
     T: Trait<{std::intrinsics::type_name::<T>()}>
     //[min]~^ ERROR generic parameters may not be used in const operations
-    //[full]~^^ ERROR constant expression depends on a generic parameter
 {
     t: T
 }
index 32939dcd2861bd1c7432c31238ab3e974f4184e2..bc3c09238f255e379026150e7006beb7f8c2bc8c 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(adt_const_params, const_generics_defaults)]
 #![allow(incomplete_features)]
 
 #[derive(PartialEq, Eq)]
index f59eb60cb38f0ed488f5308082b8f29b7cc05e0f..6a10ee267df93eda14f385bb9b39d788f231e708 100644 (file)
@@ -1,5 +1,5 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
 
 // All of these three items must be in `lib2` to reproduce the error
 
@@ -10,6 +10,6 @@ pub trait TypeFn {
 pub struct GenericType<const B: i8>;
 
 // Removing the braces around `42` resolves the crash
-impl TypeFn for GenericType<{ 42 }> {
+impl TypeFn for GenericType<{ 40 + 2 }> {
     type Output = ();
 }
index 4a6b57842217ee9ecbc1179a4dc9cfe172748d0b..de3a40860252efed356a0a70a22742a04cb4438b 100644 (file)
@@ -1,5 +1,4 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(generic_const_exprs)]
 
 pub struct Num<const N: usize>;
 
index 8416d64e1c2de1dbc72d9cfe65a126b0d9a430d9..179643a7552939e147460bfb7b3e9eda75fadbe4 100644 (file)
@@ -1,20 +1,11 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-56445-1.rs:3:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
 error[E0771]: use of non-static lifetime `'a` in const generic
-  --> $DIR/issue-56445-1.rs:8:26
+  --> $DIR/issue-56445-1.rs:9:26
    |
 LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
    |                          ^^
    |
    = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0771`.
index f7056f27cb37bd8337c6c41d5165b65150390b78..179643a7552939e147460bfb7b3e9eda75fadbe4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0771]: use of non-static lifetime `'a` in const generic
-  --> $DIR/issue-56445-1.rs:8:26
+  --> $DIR/issue-56445-1.rs:9:26
    |
 LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
    |                          ^^
index bc9e1dee853e482c592da4e5c6741e26d54c3ebd..aeef778991f067f7d6727dce3028f825f622bea0 100644 (file)
@@ -1,6 +1,7 @@
 // Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995.
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(adt_const_params))]
+#![cfg_attr(full, allow(incomplete_features))]
 #![crate_type = "lib"]
 
 use std::marker::PhantomData;
diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr
deleted file mode 100644 (file)
index c03b725..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-60818-struct-constructors.rs:3:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 6e64c78cd8c96979fa135386b1bea79b1cc96b4c..0066490dfa37a02117518ebe98fc670746160ff8 100644 (file)
@@ -1,6 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
 
 struct Generic<const V: usize>;
 
diff --git a/src/test/ui/const-generics/issues/issue-61336-1.full.stderr b/src/test/ui/const-generics/issues/issue-61336-1.full.stderr
deleted file mode 100644 (file)
index f18728e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61336-1.rs:3:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index c93b296dbb557c8a3ce974278573351beeed0a7e..beb37e63b5e5dc7c651f93d42af7097f92dee9b6 100644 (file)
@@ -1,7 +1,4 @@
 // build-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
-
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; N]
 }
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.full.stderr b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr
deleted file mode 100644 (file)
index 8f07d20..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61336-2.rs:2:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-61336-2.rs:9:5
-   |
-LL |     [x; { N }]
-   |     ^^^^^^^^^^ the trait `Copy` is not implemented for `T`
-   |
-   = note: the `Copy` trait is required because the repeated element will be copied
-help: consider restricting type parameter `T`
-   |
-LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
-   |       +++++++++++++++++++
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr
deleted file mode 100644 (file)
index 9b62ffc..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-61336-2.rs:9:5
-   |
-LL |     [x; { N }]
-   |     ^^^^^^^^^^ the trait `Copy` is not implemented for `T`
-   |
-   = note: the `Copy` trait is required because the repeated element will be copied
-help: consider restricting type parameter `T`
-   |
-LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
-   |       +++++++++++++++++++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index a1cf641ff749f66182fa75f0e34204ce3ab5ed8e..b7cd29f89323a0b04dd650b8750e9f56019f73d3 100644 (file)
@@ -1,6 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
-
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; { N }]
 }
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr
new file mode 100644 (file)
index 0000000..48aaaf5
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/issue-61336-2.rs:6:5
+   |
+LL |     [x; { N }]
+   |     ^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+help: consider restricting type parameter `T`
+   |
+LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
+   |       +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336.full.stderr b/src/test/ui/const-generics/issues/issue-61336.full.stderr
deleted file mode 100644 (file)
index 4883463..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61336.rs:2:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-61336.rs:9:5
-   |
-LL |     [x; N]
-   |     ^^^^^^ the trait `Copy` is not implemented for `T`
-   |
-   = note: the `Copy` trait is required because the repeated element will be copied
-help: consider restricting type parameter `T`
-   |
-LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
-   |       +++++++++++++++++++
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336.min.stderr b/src/test/ui/const-generics/issues/issue-61336.min.stderr
deleted file mode 100644 (file)
index dc89184..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-61336.rs:9:5
-   |
-LL |     [x; N]
-   |     ^^^^^^ the trait `Copy` is not implemented for `T`
-   |
-   = note: the `Copy` trait is required because the repeated element will be copied
-help: consider restricting type parameter `T`
-   |
-LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
-   |       +++++++++++++++++++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
index c0106ee38c206d9849f29dee9e5a480493ff9be5..80be1d8e5e5402e451bb7c51abdc42fc12bd08b8 100644 (file)
@@ -1,6 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
-
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; N]
 }
diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr
new file mode 100644 (file)
index 0000000..665a1a6
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/issue-61336.rs:6:5
+   |
+LL |     [x; N]
+   |     ^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+help: consider restricting type parameter `T`
+   |
+LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
+   |       +++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61422.full.stderr b/src/test/ui/const-generics/issues/issue-61422.full.stderr
deleted file mode 100644 (file)
index ac6c378..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61422.rs:3:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 421f696f3fd8d92eeaf191fd116cd87ba5c8d513..0b9cf40d855545f10f1105a1ca385fced65e327c 100644 (file)
@@ -1,7 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
-
 use std::mem;
 
 // Neither of the uninits below are currently accepted as not UB, however,
diff --git a/src/test/ui/const-generics/issues/issue-61432.full.stderr b/src/test/ui/const-generics/issues/issue-61432.full.stderr
deleted file mode 100644 (file)
index 82b36de..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61432.rs:3:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 97ab07daccefb94843eac8d33c3ebd3dceca98ad..6192af82afb2849f636fcdd45d77bf0764a8f9c5 100644 (file)
@@ -1,13 +1,6 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
 
 fn promote<const N: i32>() {
-    // works:
-    //
-    // let n = N;
-    // let _ = &n;
-
     let _ = &N;
 }
 
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.full.stderr
deleted file mode 100644 (file)
index 56deec1..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:6:40
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                        ^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61522-array-len-succ.rs:11:24
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                        ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.min.stderr
deleted file mode 100644 (file)
index 36a0a37..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:6:45
-   |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-   |                                             ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61522-array-len-succ.rs:11:30
-   |
-LL |     fn inner(&self) -> &[u8; COUNT + 1] {
-   |                              ^^^^^ cannot perform const operation using `COUNT`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issues/issue-61522-array-len-succ.rs
deleted file mode 100644 (file)
index d4a948b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used
-
-impl<const COUNT: usize> MyArray<COUNT> {
-    fn inner(&self) -> &[u8; COUNT + 1] {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        //[min]~^^ ERROR generic parameters may not be used
-        &self.0
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-61747.full.stderr b/src/test/ui/const-generics/issues/issue-61747.full.stderr
deleted file mode 100644 (file)
index b7f6634..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61747.rs:2:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61747.rs:7:23
-   |
-LL |     fn successor() -> Const<{C + 1}> {
-   |                       ^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error; 1 warning emitted
-
diff --git a/src/test/ui/const-generics/issues/issue-61747.min.stderr b/src/test/ui/const-generics/issues/issue-61747.min.stderr
deleted file mode 100644 (file)
index b85533c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61747.rs:7:30
-   |
-LL |     fn successor() -> Const<{C + 1}> {
-   |                              ^ cannot perform const operation using `C`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `C`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs
deleted file mode 100644 (file)
index 3aa2e6a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
-
-struct Const<const N: usize>;
-
-impl<const C: usize> Const<{C}> {
-    fn successor() -> Const<{C + 1}> {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        //[min]~^^ ERROR generic parameters may not be used
-        Const
-    }
-}
-
-fn main() {
-    let _x: Const::<2> = Const::<1>::successor();
-}
diff --git a/src/test/ui/const-generics/issues/issue-61935.full.stderr b/src/test/ui/const-generics/issues/issue-61935.full.stderr
deleted file mode 100644 (file)
index b970f4e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-61935.rs:9:14
-   |
-LL |         Self:FooImpl<{N==0}>
-   |              ^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-61935.min.stderr b/src/test/ui/const-generics/issues/issue-61935.min.stderr
deleted file mode 100644 (file)
index 9382dca..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-61935.rs:9:23
-   |
-LL |         Self:FooImpl<{N==0}>
-   |                       ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-61935.rs b/src/test/ui/const-generics/issues/issue-61935.rs
deleted file mode 100644 (file)
index ed861c6..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-trait Foo {}
-
-impl<const N: usize> Foo for [(); N]
-    where
-        Self:FooImpl<{N==0}>
-//[full]~^ERROR constant expression depends on a generic parameter
-//[min]~^^ERROR generic parameters may not be used in const operations
-{}
-
-trait FooImpl<const IS_ZERO: bool>{}
-
-impl FooImpl<true> for [(); 0] {}
-
-impl<const N:usize> FooImpl<false> for [();N] {}
-
-fn foo(_: impl Foo) {}
-
-fn main() {
-    foo([]);
-    foo([()]);
-}
index 1a0e46e599d95c0f0f4e32056d9b2f0e1f6cb3a1..fa76aeae901d183c7d9010982665fa385c77ab3c 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub trait BitLen: Sized {
     const BIT_LEN: usize;
 }
diff --git a/src/test/ui/const-generics/issues/issue-62220.full.stderr b/src/test/ui/const-generics/issues/issue-62220.full.stderr
deleted file mode 100644 (file)
index 373360c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62220.rs:12:27
-   |
-LL |     pub fn trunc(self) -> (TruncatedVector<T, { N }>, T) {
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-62220.min.stderr b/src/test/ui/const-generics/issues/issue-62220.min.stderr
deleted file mode 100644 (file)
index 72311d0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-62220.rs:7:59
-   |
-LL | pub type TruncatedVector<T, const N: usize> = Vector<T, { N - 1 }>;
-   |                                                           ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-62220.rs b/src/test/ui/const-generics/issues/issue-62220.rs
deleted file mode 100644 (file)
index c26784c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct Vector<T, const N: usize>([T; N]);
-
-pub type TruncatedVector<T, const N: usize> = Vector<T, { N - 1 }>;
-//[min]~^ ERROR generic parameters may not be used in const operations
-
-impl<T, const N: usize> Vector<T, { N }> {
-    /// Drop the last component and return the vector with one fewer dimension.
-    pub fn trunc(self) -> (TruncatedVector<T, { N }>, T) {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        unimplemented!()
-    }
-}
-
-fn vec4<T>(a: T, b: T, c: T, d: T) -> Vector<T, 4> {
-    Vector([a, b, c, d])
-}
-
-fn main() {
-    let (_xyz, _w): (TruncatedVector<u32, 4>, u32) = vec4(0u32, 1, 2, 3).trunc();
-}
diff --git a/src/test/ui/const-generics/issues/issue-62456.full.stderr b/src/test/ui/const-generics/issues/issue-62456.full.stderr
deleted file mode 100644 (file)
index 833e70c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62456.rs:6:20
-   |
-LL |     let _ = [0u64; N + 1];
-   |                    ^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-62456.min.stderr b/src/test/ui/const-generics/issues/issue-62456.min.stderr
deleted file mode 100644 (file)
index 920318f..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-62456.rs:6:20
-   |
-LL |     let _ = [0u64; N + 1];
-   |                    ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs
deleted file mode 100644 (file)
index e24cf36..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-fn foo<const N: usize>() {
-    let _ = [0u64; N + 1];
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-62504.full.stderr b/src/test/ui/const-generics/issues/issue-62504.full.stderr
deleted file mode 100644 (file)
index efbcdc3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-62504.rs:18:21
-   |
-LL |         ArrayHolder([0; Self::SIZE])
-   |                     ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
-   |
-   = note: expected type `X`
-              found type `Self::SIZE`
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62504.rs:18:25
-   |
-LL |         ArrayHolder([0; Self::SIZE])
-   |                         ^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-62504.min.stderr b/src/test/ui/const-generics/issues/issue-62504.min.stderr
deleted file mode 100644 (file)
index 5d45e30..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-62504.rs:18:21
-   |
-LL |         ArrayHolder([0; Self::SIZE])
-   |                     ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
-   |
-   = note: expected array `[u32; X]`
-              found array `[u32; _]`
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62504.rs:18:25
-   |
-LL |         ArrayHolder([0; Self::SIZE])
-   |                         ^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-62504.rs b/src/test/ui/const-generics/issues/issue-62504.rs
deleted file mode 100644 (file)
index 1b70cd1..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// revisions: full min
-#![allow(incomplete_features)]
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-trait HasSize {
-    const SIZE: usize;
-}
-
-impl<const X: usize> HasSize for ArrayHolder<X> {
-    const SIZE: usize = X;
-}
-
-struct ArrayHolder<const X: usize>([u32; X]);
-
-impl<const X: usize> ArrayHolder<X> {
-    pub const fn new() -> Self {
-        ArrayHolder([0; Self::SIZE])
-        //~^ ERROR constant expression depends on a generic parameter
-        //~| ERROR mismatched types
-    }
-}
-
-fn main() {
-    let mut array = ArrayHolder::new();
-}
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
deleted file mode 100644 (file)
index 5c9387d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `NoMatch` is forbidden as the type of a const generic parameter
-  --> $DIR/issue-62579-no-match.rs:9:17
-   |
-LL | fn foo<const T: NoMatch>() -> bool {
-   |                 ^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs
deleted file mode 100644 (file)
index 46813f5..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// [full] run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-#[derive(PartialEq, Eq)]
-struct NoMatch;
-
-fn foo<const T: NoMatch>() -> bool {
-    //[min]~^ ERROR `NoMatch` is forbidden as the type of a const generic parameter
-    true
-}
-
-fn main() {
-    foo::<{NoMatch}>();
-}
index 08f6454fa2dfefcac006150720974f861c126a03..f074a65313f12e3156ed9f8983d039eb031e7ae8 100644 (file)
@@ -4,21 +4,13 @@ error[E0770]: the type of const parameters must not depend on other generic para
 LL | fn foo<const N: usize, const A: [u8; N]>() {}
    |                                      ^ the type must not depend on the parameter `N`
 
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-62878.rs:10:14
-   |
-LL |     foo::<_, {[1]}>();
-   |              ^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
 error[E0308]: mismatched types
   --> $DIR/issue-62878.rs:10:15
    |
 LL |     foo::<_, {[1]}>();
    |               ^^^ expected `usize`, found array `[{integer}; 1]`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0770.
 For more information about an error, try `rustc --explain E0308`.
index e4a71fe061869e7ab45016b3a9b05b3a042e345a..af029a6516bc625ae142e24a1a016c1583c1f99d 100644 (file)
@@ -11,7 +11,7 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
    |                                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index fb6257696b96d5a66abd2ff05bdaedf9725ac01b..38f5ff77b56a9ac1e5d7a37e3bbbb1744f84ade1 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics, generic_arg_infer))]
+#![cfg_attr(full, feature(adt_const_params, generic_arg_infer))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn foo<const N: usize, const A: [u8; N]>() {}
@@ -9,5 +9,4 @@
 fn main() {
     foo::<_, {[1]}>();
     //[full]~^ ERROR mismatched types
-    //[full]~| ERROR constant expression
 }
index 2fb38addb2d812f6324d79b067da3f0c0433ded4..b1141cf3bdfbf03486ef60ade77968382d9a0c27 100644 (file)
@@ -5,7 +5,7 @@ LL | fn test<const T: &'static dyn A>() {
    |                  ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:9:18
index 334e2aac02a4814cd2ea692e86a79ae74097fc19..01a6caa130f38223e3b873c556ca255a7b79fce3 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 trait A {}
diff --git a/src/test/ui/const-generics/issues/issue-64494.full.stderr b/src/test/ui/const-generics/issues/issue-64494.full.stderr
deleted file mode 100644 (file)
index abb26d6..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-64494.rs:15:53
-   |
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
-   |                                                     ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-64494.rs:18:53
-   |
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
-   |                                                     ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-64494.min.stderr b/src/test/ui/const-generics/issues/issue-64494.min.stderr
deleted file mode 100644 (file)
index 846db0c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-64494.rs:15:38
-   |
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
-   |                                      ^^^^^^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-64494.rs:18:38
-   |
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
-   |                                      ^^^^^^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0119]: conflicting implementations of trait `MyTrait`
-  --> $DIR/issue-64494.rs:18:1
-   |
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
-   | ------------------------------------ first implementation here
-...
-LL | impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/const-generics/issues/issue-64494.rs b/src/test/ui/const-generics/issues/issue-64494.rs
deleted file mode 100644 (file)
index 96d1920..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-trait Foo {
-    const VAL: usize;
-}
-
-trait MyTrait {}
-
-trait True {}
-struct Is<const T: bool>;
-impl True for Is<{true}> {}
-
-impl<T: Foo> MyTrait for T where Is<{T::VAL == 5}>: True {}
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
-impl<T: Foo> MyTrait for T where Is<{T::VAL == 6}>: True {}
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
-//[min]~| ERROR conflicting implementations of trait `MyTrait`
-
-fn main() {}
index 8c603b74b90710d8f877e642f050e9b17e23bd0e..969289b26e80d205cf284570f8f4eda3993105b8 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct Foo<const D: usize> {
     state: Option<[u8; D]>,
 }
diff --git a/src/test/ui/const-generics/issues/issue-64519.stderr b/src/test/ui/const-generics/issues/issue-64519.stderr
deleted file mode 100644 (file)
index 6552aea..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-64519.rs:3:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/issues/issue-66205.full.stderr b/src/test/ui/const-generics/issues/issue-66205.full.stderr
deleted file mode 100644 (file)
index 7e150f5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-66205.rs:7:12
-   |
-LL |     fact::<{ N - 1 }>();
-   |            ^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-66205.min.stderr b/src/test/ui/const-generics/issues/issue-66205.min.stderr
deleted file mode 100644 (file)
index b41793b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-66205.rs:7:14
-   |
-LL |     fact::<{ N - 1 }>();
-   |              ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-66205.rs b/src/test/ui/const-generics/issues/issue-66205.rs
deleted file mode 100644 (file)
index 14249b6..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-#![allow(dead_code, unconditional_recursion)]
-
-fn fact<const N: usize>() {
-    fact::<{ N - 1 }>();
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issues/issue-66596-impl-trait-for-str-const-arg.min.stderr
deleted file mode 100644 (file)
index e96b9e7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:8:25
-   |
-LL | trait Trait<const NAME: &'static str> {
-   |                         ^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
index 2a741ba87a980957e337143885379e9b47eed37a..091419f0c52ec822bc80c4a427b4a2083f9a6ad0 100644 (file)
@@ -1,12 +1,9 @@
-//[full] check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+// check-pass
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
 
 
 trait Trait<const NAME: &'static str> {
-//[min]~^ ERROR `&'static str` is forbidden
     type Assoc;
 }
 
index a871b118dcc5265d3df78752affde7908eefacaf..a0b3f91220710ac003cd6aed43cfd61187dbd412 100644 (file)
@@ -1,7 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 pub struct Tuple;
 
index ed35a5f7c0a879409011988d169205f7d59ea994..69425b25eaee4c6101e7ebd9635d8aff36b982ce 100644 (file)
@@ -1,7 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait Baz {
     type Quaks;
diff --git a/src/test/ui/const-generics/issues/issue-67185-2.full.stderr b/src/test/ui/const-generics/issues/issue-67185-2.full.stderr
deleted file mode 100644 (file)
index 19f419c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:16:1
-   |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-   = help: see issue #48214
-   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:16:1
-   |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-   = help: see issue #48214
-   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
-
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:6
-   |
-LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:20:29
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:6
-   |
-LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:19:34
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:30:14
-   |
-LL | fn f(_: impl Foo) {}
-   |              ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:19:34
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:30:14
-   |
-LL | fn f(_: impl Foo) {}
-   |              ^^^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:20:29
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-67185-2.min.stderr b/src/test/ui/const-generics/issues/issue-67185-2.min.stderr
deleted file mode 100644 (file)
index 19f419c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:16:1
-   |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-   = help: see issue #48214
-   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:16:1
-   |
-LL | / trait Foo
-LL | |
-LL | |     where
-LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
-LL | |         <u8 as Baz>::Quaks: Bar,
-LL | | {
-LL | | }
-   | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-   = help: see issue #48214
-   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
-
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:6
-   |
-LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:20:29
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:26:6
-   |
-LL | impl Foo for FooImpl {}
-   |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:19:34
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:30:14
-   |
-LL | fn f(_: impl Foo) {}
-   |              ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:19:34
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         [<u8 as Baz>::Quaks; 2]: Bar,
-   |                                  ^^^ required by this bound in `Foo`
-
-error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
-  --> $DIR/issue-67185-2.rs:30:14
-   |
-LL | fn f(_: impl Foo) {}
-   |              ^^^ the trait `Bar` is not implemented for `[u16; 3]`
-   |
-   = help: the following implementations were found:
-             <[[u16; 3]; 3] as Bar>
-             <[u16; 4] as Bar>
-note: required by a bound in `Foo`
-  --> $DIR/issue-67185-2.rs:20:29
-   |
-LL | trait Foo
-   |       --- required by a bound in this
-...
-LL |         <u8 as Baz>::Quaks: Bar,
-   |                             ^^^ required by this bound in `Foo`
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
index 94a713d7cf95e58baa6cdbe8f315a4558e821734..c1a04e201474959f41e926c61b20c4579de57725 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait Baz {
     type Quaks;
 }
diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr
new file mode 100644 (file)
index 0000000..7167bea
--- /dev/null
@@ -0,0 +1,111 @@
+error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:12:1
+   |
+LL | / trait Foo
+LL | |
+LL | |     where
+LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
+LL | |         <u8 as Baz>::Quaks: Bar,
+LL | | {
+LL | | }
+   | |_^ the trait `Bar` is not implemented for `[u16; 3]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:12:1
+   |
+LL | / trait Foo
+LL | |
+LL | |     where
+LL | |         [<u8 as Baz>::Quaks; 2]: Bar,
+LL | |         <u8 as Baz>::Quaks: Bar,
+LL | | {
+LL | | }
+   | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+   = help: see issue #48214
+   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
+
+error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:22:6
+   |
+LL | impl Foo for FooImpl {}
+   |      ^^^ the trait `Bar` is not implemented for `[u16; 3]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+note: required by a bound in `Foo`
+  --> $DIR/issue-67185-2.rs:16:29
+   |
+LL | trait Foo
+   |       --- required by a bound in this
+...
+LL |         <u8 as Baz>::Quaks: Bar,
+   |                             ^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:22:6
+   |
+LL | impl Foo for FooImpl {}
+   |      ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+note: required by a bound in `Foo`
+  --> $DIR/issue-67185-2.rs:15:34
+   |
+LL | trait Foo
+   |       --- required by a bound in this
+...
+LL |         [<u8 as Baz>::Quaks; 2]: Bar,
+   |                                  ^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:26:14
+   |
+LL | fn f(_: impl Foo) {}
+   |              ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+note: required by a bound in `Foo`
+  --> $DIR/issue-67185-2.rs:15:34
+   |
+LL | trait Foo
+   |       --- required by a bound in this
+...
+LL |         [<u8 as Baz>::Quaks; 2]: Bar,
+   |                                  ^^^ required by this bound in `Foo`
+
+error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied
+  --> $DIR/issue-67185-2.rs:26:14
+   |
+LL | fn f(_: impl Foo) {}
+   |              ^^^ the trait `Bar` is not implemented for `[u16; 3]`
+   |
+   = help: the following implementations were found:
+             <[[u16; 3]; 3] as Bar>
+             <[u16; 4] as Bar>
+note: required by a bound in `Foo`
+  --> $DIR/issue-67185-2.rs:16:29
+   |
+LL | trait Foo
+   |       --- required by a bound in this
+...
+LL |         <u8 as Baz>::Quaks: Bar,
+   |                             ^^^ required by this bound in `Foo`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 0fe65272f1b78d0bea6437c2da47606da92fc59d..5386ef56a245a8b1df56bb7e458bbc96dfe4625d 100644 (file)
@@ -1,15 +1,15 @@
-warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/issue-67375.rs:8:12
+error: overly complex generic constant
+  --> $DIR/issue-67375.rs:7:17
    |
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^----------^^^^^^^^^^^^
+   |                    |
+   |                    unsupported rvalue
    |
-   = note: `#[warn(const_evaluatable_unchecked)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+   = help: consider moving this anonymous constant into a `const` function
 
 error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
+  --> $DIR/issue-67375.rs:5:12
    |
 LL | struct Bug<T> {
    |            ^ unused parameter
@@ -17,6 +17,6 @@ LL | struct Bug<T> {
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
    = help: if you intended `T` to be a const parameter, use `const T: usize` instead
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0392`.
index be81fa921297b2a67ffa0ed00d89a2c4ed011318..5256d96c876941054b27273e4e4fe3cb71fe405d 100644 (file)
@@ -1,14 +1,14 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-67375.rs:8:25
+  --> $DIR/issue-67375.rs:7:25
    |
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
    |                         ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0392]: parameter `T` is never used
-  --> $DIR/issue-67375.rs:6:12
+  --> $DIR/issue-67375.rs:5:12
    |
 LL | struct Bug<T> {
    |            ^ unused parameter
index a8875b8b6bfcabf59e148ac2b3917686c2fe627b..b5b842a15ae0c142c98042079777ab46653b702e 100644 (file)
@@ -1,14 +1,12 @@
 // revisions: full min
-
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 
 struct Bug<T> {
     //~^ ERROR parameter `T` is never used
     inner: [(); { [|_: &T| {}; 0].len() }],
     //[min]~^ ERROR generic parameters may not be used in const operations
-    //[full]~^^ WARN cannot use constants which depend on generic parameters in types
-    //[full]~^^^ WARN this was previously accepted by the compiler
+    //[full]~^^ ERROR overly complex generic constant
 }
 
 fn main() {}
index dcbe5b94a6281dfc3d70c297b8bb235e45fb0b00..f1a426c3c586199e4c272976d2278e6a52a22e9b 100644 (file)
@@ -1,10 +1,10 @@
-error: constant expression depends on a generic parameter
+error: unconstrained generic constant
   --> $DIR/issue-67739.rs:11:15
    |
 LL |         [0u8; mem::size_of::<Self::Associated>()];
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: this may fail depending on what value the parameter takes
+   = help: try adding a `where` bound using this expression: `where [(); mem::size_of::<Self::Associated>()]:`
 
 error: aborting due to previous error
 
index e4960e56c9e4ea7ce9e875860b19a5b6c23ab78f..de0eb7f509ae56aee7915445fc96821f1db25fe4 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 use std::mem;
@@ -9,7 +9,8 @@ pub trait Trait {
 
     fn associated_size(&self) -> usize {
         [0u8; mem::size_of::<Self::Associated>()];
-        //~^ ERROR constant expression depends on a generic parameter
+        //[min]~^ ERROR constant expression depends on a generic parameter
+        //[full]~^^ ERROR unconstrained generic constant
         0
     }
 }
index 63c50b5ca542387bc5058f9b94c222a2314e313c..1edc7828caad2553ce00308dd7f5a1283c70cc24 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-67945-1.rs:13:20
+  --> $DIR/issue-67945-1.rs:10:20
    |
 LL | struct Bug<S> {
    |            - this type parameter
@@ -13,7 +13,7 @@ LL |         let x: S = MaybeUninit::uninit();
                        found union `MaybeUninit<_>`
 
 error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
+  --> $DIR/issue-67945-1.rs:7:12
    |
 LL | struct Bug<S> {
    |            ^ unused parameter
index 074d36c8ef3ed2d41a3894f4115f7636fac0c387..eee04eb75a2588ca5720abdb17d6e6e45ba6156d 100644 (file)
@@ -1,23 +1,23 @@
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:13:16
+  --> $DIR/issue-67945-1.rs:10:16
    |
 LL |         let x: S = MaybeUninit::uninit();
    |                ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-1.rs:16:45
+  --> $DIR/issue-67945-1.rs:13:45
    |
 LL |         let b = &*(&x as *const _ as *const S);
    |                                             ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-1.rs:10:12
+  --> $DIR/issue-67945-1.rs:7:12
    |
 LL | struct Bug<S> {
    |            ^ unused parameter
index 84737e4e9857839380f0b6569e9ca132027e0860..7b7e8428639c7d486b7e6073a84546e3aecba872 100644 (file)
@@ -1,11 +1,8 @@
 // revisions: full min
-
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-use std::marker::PhantomData;
+#![cfg_attr(full, feature(generic_const_exprs))]
 
-use std::mem::{self, MaybeUninit};
+use std::mem::MaybeUninit;
 
 struct Bug<S> {
     //~^ ERROR parameter `S` is never used
index b900406023117111434003fc8c6cf261bd131300..118cf447c01e2aefaed3a6f0eef4986570fb875f 100644 (file)
@@ -1,27 +1,17 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-67945-2.rs:11:20
+error: overly complex generic constant
+  --> $DIR/issue-67945-2.rs:7:13
    |
-LL | struct Bug<S> {
-   |            - this type parameter
-...
-LL |         let x: S = MaybeUninit::uninit();
-   |                -   ^^^^^^^^^^^^^^^^^^^^^ expected type parameter `S`, found union `MaybeUninit`
-   |                |
-   |                expected due to this
+LL |       A: [(); {
+   |  _____________^
+LL | |
+LL | |         let x: Option<Box<Self>> = None;
+   | |                                    ---- unsupported rvalue
+LL | |
+LL | |         0
+LL | |     }],
+   | |_____^
    |
-   = note: expected type parameter `S`
-                       found union `MaybeUninit<_>`
+   = help: consider moving this anonymous constant into a `const` function
 
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0392.
-For more information about an error, try `rustc --explain E0308`.
index c06df79f8428c51a3b3da3e8ea9cafd31b319bb6..6e07af1e672a8ed03c29b7365d8c92fb20d3b707 100644 (file)
@@ -1,30 +1,8 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:11:16
+error: generic `Self` types are currently not permitted in anonymous constants
+  --> $DIR/issue-67945-2.rs:9:27
    |
-LL |         let x: S = MaybeUninit::uninit();
-   |                ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-67945-2.rs:14:45
-   |
-LL |         let b = &*(&x as *const _ as *const S);
-   |                                             ^ cannot perform const operation using `S`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/issue-67945-2.rs:8:12
-   |
-LL | struct Bug<S> {
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
+LL |         let x: Option<Box<Self>> = None;
+   |                           ^^^^
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0392`.
index 4a46786e9a9bf3c3751f1a1df06d07fb5584a390..cbb4e14eccf72957499e6c66eb27b04daafdcb2f 100644 (file)
@@ -1,20 +1,16 @@
 // revisions: full min
 
 #![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 
-use std::mem::MaybeUninit;
-
-struct Bug<S> {
-    //~^ ERROR parameter `S` is never used
+struct Bug<S: ?Sized> {
     A: [(); {
-        let x: S = MaybeUninit::uninit();
-        //[min]~^ ERROR generic parameters may not be used in const operations
-        //[full]~^^ ERROR mismatched types
-        let b = &*(&x as *const _ as *const S);
-        //[min]~^ ERROR generic parameters may not be used in const operations
+        //[full]~^ ERROR overly complex generic constant
+        let x: Option<Box<Self>> = None;
+        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
         0
     }],
+    B: S
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.full.stderr b/src/test/ui/const-generics/issues/issue-67945-3.full.stderr
deleted file mode 100644 (file)
index fa66252..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-67945-3.rs:7:8
-   |
-LL |       A: [(); {
-   |  ________^
-LL | |
-LL | |         let x: Option<Box<Self>> = None;
-LL | |
-LL | |         0
-LL | |     }],
-   | |______^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.min.stderr b/src/test/ui/const-generics/issues/issue-67945-3.min.stderr
deleted file mode 100644 (file)
index 5c30429..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/issue-67945-3.rs:9:27
-   |
-LL |         let x: Option<Box<Self>> = None;
-   |                           ^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-67945-3.rs b/src/test/ui/const-generics/issues/issue-67945-3.rs
deleted file mode 100644 (file)
index 5bad61c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// revisions: full min
-
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-struct Bug<S: ?Sized> {
-    A: [(); {
-        //[full]~^ ERROR constant expression depends on a generic parameter
-        let x: Option<Box<Self>> = None;
-        //[min]~^ ERROR generic `Self` types are currently not permitted in anonymous constants
-        0
-    }],
-    B: S
-}
-
-fn main() {}
index 43c3999133c650b934f34ff5b965565a4b151fc3..ad5710baae2bf21bdefb7866bfd06ee0bd9d49f0 100644 (file)
@@ -1,9 +1,7 @@
 // aux-build:impl-const.rs
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
 
 extern crate impl_const;
 
index da4cbd3081f894928bfc27222575eb181fa060d5..9f370b0f510f4f30d5f235d878aa3bdb0ba21154 100644 (file)
@@ -5,7 +5,7 @@ LL | impl <const N: usize> Collatz<{Some(N)}> {}
    |                                     ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
   --> $DIR/issue-68366.rs:11:13
index 37afed62327d612b4881e4af24ee05479e698b12..4c2741ab43371dd1fb8c899ec1883f05d5b5fa7b 100644 (file)
@@ -3,7 +3,7 @@
 // type.
 
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Collatz<const N: Option<usize>>;
index 0bb23be1eb4ea3bea13dc7fe5cf876d78a95ea47..c3c9141e424d401f65402bddc139c51961bf2ae0 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub struct S(u8);
 
 impl S {
index 4782b1d98eba343168adbc2055d3779b0ff7588e..df04c4896b45a23ad5aa77c6bb316d8efc9d8b03 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 0]> {}
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index ddea3e8ab6587d9993eeada78b59cf40ad8e8ed3..3ef1ad45edfd40855b023159c960e0ba3e9820a5 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Const<const V: [usize; 0]> {}
index d0c190b91b040e043121ed0fa0620335b46ac1e1..1b4517087e223e257c79b3fd1e17b10dac1de26d 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const V: [usize; 0] > {}
    |                     ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index 56afd9b2a154a75539e115026dc3e9163ec0c312..93477be41b5903015da6e2998caac298fb179222 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<const V: [usize; 0] > {}
diff --git a/src/test/ui/const-generics/issues/issue-68977.full.stderr b/src/test/ui/const-generics/issues/issue-68977.full.stderr
deleted file mode 100644 (file)
index 25dcd88..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-68977.rs:34:44
-   |
-LL |     FxpStorageHelper<INT_BITS, FRAC_BITS>: FxpStorage,
-   |                                            ^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-68977.min.stderr b/src/test/ui/const-generics/issues/issue-68977.min.stderr
deleted file mode 100644 (file)
index 0b3d5b9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-68977.rs:28:17
-   |
-LL |     PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
-   |                 ^^^^^^^^ cannot perform const operation using `INT_BITS`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `INT_BITS`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-68977.rs:28:28
-   |
-LL |     PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
-   |                            ^^^^^^^^^ cannot perform const operation using `FRAC_BITS`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `FRAC_BITS`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-68977.rs b/src/test/ui/const-generics/issues/issue-68977.rs
deleted file mode 100644 (file)
index a0ffcc8..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct PhantomU8<const X: u8>;
-
-trait FxpStorage {
-    type SInt; // Add arithmetic traits as needed.
-}
-
-macro_rules! fxp_storage_impls {
-    ($($($n:literal)|+ => $sint:ty),* $(,)?) => {
-        $($(impl FxpStorage for PhantomU8<$n> {
-            type SInt = $sint;
-        })*)*
-    }
-}
-
-fxp_storage_impls! {
-    1 => i8,
-    2 => i16,
-    3 | 4 => i32,
-    5 | 6 | 7 | 8 => i64,
-    9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 => i128,
-}
-
-type FxpStorageHelper<const INT_BITS: u8, const FRAC_BITS: u8> =
-    PhantomU8<{(INT_BITS + FRAC_BITS + 7) / 8}>;
-    //[min]~^ ERROR generic parameters may not be used in const operations
-    //[min]~| ERROR generic parameters may not be used in const operations
-
-struct Fxp<const INT_BITS: u8, const FRAC_BITS: u8>
-where
-    FxpStorageHelper<INT_BITS, FRAC_BITS>: FxpStorage,
-    //[full]~^ ERROR constant expression depends on a generic parameter
-{
-    storage: <FxpStorageHelper<INT_BITS, FRAC_BITS> as FxpStorage>::SInt,
-}
-
-fn main() {
-    Fxp::<1, 15> { storage: 0i16 };
-    Fxp::<2, 15> { storage: 0i32 };
-}
index 45318ca68fcc586f03da6804d73fbccac8cf0c03..63d7fde78ac8a1852e4a03fe40eda2bed9c192ec 100644 (file)
@@ -1,8 +1,6 @@
-#![feature(const_generics)]
-#![allow(incomplete_features, unused_braces)]
-
+// run-pass
 trait Bar<T> {}
-impl<T> Bar<T> for [u8; {7}] {}
+impl<T> Bar<T> for [u8; 7] {}
 
 struct Foo<const N: usize> {}
 impl<const N: usize> Foo<N>
@@ -14,5 +12,4 @@ fn foo() {}
 
 fn main() {
     Foo::foo();
-    //~^ ERROR the function or associated item
 }
diff --git a/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr b/src/test/ui/const-generics/issues/issue-69654-run-pass.stderr
deleted file mode 100644 (file)
index a82a606..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied
-  --> $DIR/issue-69654-run-pass.rs:16:10
-   |
-LL | struct Foo<const N: usize> {}
-   | -------------------------- function or associated item `foo` not found for this
-...
-LL |     Foo::foo();
-   |          ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds
-   |
-   = note: the following trait bounds were not satisfied:
-           `[u8; _]: Bar<[(); _]>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/const-generics/issues/issue-69654.rs b/src/test/ui/const-generics/issues/issue-69654.rs
deleted file mode 100644 (file)
index b1214b1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
-trait Bar<T> {}
-impl<T> Bar<T> for [u8; T] {}
-//~^ ERROR expected value, found type parameter `T`
-
-struct Foo<const N: usize> {}
-impl<const N: usize> Foo<N>
-where
-    [u8; N]: Bar<[(); N]>,
-{
-    fn foo() {}
-}
-
-fn main() {
-    Foo::foo();
-    //~^ ERROR the function or associated item
-}
diff --git a/src/test/ui/const-generics/issues/issue-69654.stderr b/src/test/ui/const-generics/issues/issue-69654.stderr
deleted file mode 100644 (file)
index 0ce7640..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-error[E0423]: expected value, found type parameter `T`
-  --> $DIR/issue-69654.rs:5:25
-   |
-LL | impl<T> Bar<T> for [u8; T] {}
-   |                         ^ not a value
-
-error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: usize}>`, but its trait bounds were not satisfied
-  --> $DIR/issue-69654.rs:17:10
-   |
-LL | struct Foo<const N: usize> {}
-   | -------------------------- function or associated item `foo` not found for this
-...
-LL |     Foo::foo();
-   |          ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds
-   |
-   = note: the following trait bounds were not satisfied:
-           `[u8; _]: Bar<[(); _]>`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0423, E0599.
-For more information about an error, try `rustc --explain E0423`.
index 5c118d245a1ec326106db55922ac9b93af357798..0027cd46a519f921742e5a1a61aaa3d6b40784e3 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 const L: usize = 4;
 
index f82131262d6e31017e7b694f78940bf536b5ebea..cfd5e784ec4045ba1c51ff0bd61d730a25abf0aa 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn main() {
     <()>::foo();
 }
index 9e912b691773bcbcac6bddb8ab0bc8a136cbf701..3961941f81fa97d3ba9fcb693207fc5b1ffcdc90 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub trait Trait<const N: usize>: From<<Self as Trait<N>>::Item> {
   type Item;
 }
index f0554823273a8f478e85fa64b790374d4fca7b08..2ec37cc3a1be5dda36b4455e85abb85272891f91 100644 (file)
@@ -1,8 +1,4 @@
 // build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 pub fn works() {
     let array/*: [_; _]*/ = default_array();
index 21cefc09c253a8b27ede78c0d55d42e5690b4d47..95e548428747f8256ffe1ff2cc0752e35c056d4d 100644 (file)
@@ -1,8 +1,4 @@
 // build-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 fn works() {
     let array/*: [u8; _]*/ = default_byte_array();
index 8f8d753d0a75fa5b25c6a96b28684245859e5f95..d458d7b2e8713d508eaf3b10837f9e25eaa87a12 100644 (file)
@@ -1,6 +1,4 @@
 // check-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
 #![deny(dead_code)]
 
 // We previously incorrectly linted `L` as unused here.
index 189a32570f76b6245c319e44a0500bc9ab924296..a76488249173ae434218d642333dc294fa7e3567 100644 (file)
@@ -1,7 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait T<const A: usize> {
     fn f();
index 7b1a2f98dfeba2b4a1a147ce0de97255a2414116..1f5880f368ee2c4c2d6f74a38ef96fb6f93fe1c2 100644 (file)
@@ -4,14 +4,6 @@ error[E0770]: the type of const parameters must not depend on other generic para
 LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
    |                                           ^^^ the type must not depend on the parameter `LEN`
 
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-71169.rs:10:14
-   |
-LL |     foo::<4, DATA>();
-   |              ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0770`.
index 1c6e08adffdffaf748b65ddead0e9450af64ea9d..87ed2d4f8da8cc6cdd616f0552194b22c6886f97 100644 (file)
@@ -11,7 +11,7 @@ LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
    |                                      ^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index a574da4b6b31dc7411f6ff2d6ae4914ba64572ba..617149a841893825a1823c6f14ad7d8e806c1000 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
@@ -8,5 +8,4 @@
 fn main() {
     const DATA: [u8; 4] = *b"ABCD";
     foo::<4, DATA>();
-    //[full]~^ ERROR constant expression depends on
 }
index 78dee1717f1fade104a9b6e0a931b8b7bb449e16..57fd72b12846ef3c47b5ea5e272938c66ea212e4 100644 (file)
@@ -1,6 +1,4 @@
-// check-pass
-
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features, const_evaluatable_unchecked)]
 
 use std::marker::PhantomData;
@@ -10,7 +8,7 @@ struct DataHolder<T> {
 }
 
 impl<T: Copy> DataHolder<T> {
-    const ITEM_IS_COPY: [(); 1 - {
+    const ITEM_IS_COPY: [(); 1 - { //~ ERROR unconstrained generic constant
         trait NotCopy {
             const VALUE: bool = false;
         }
diff --git a/src/test/ui/const-generics/issues/issue-71202.stderr b/src/test/ui/const-generics/issues/issue-71202.stderr
new file mode 100644 (file)
index 0000000..2775406
--- /dev/null
@@ -0,0 +1,33 @@
+error: unconstrained generic constant
+  --> $DIR/issue-71202.rs:11:5
+   |
+LL | /     const ITEM_IS_COPY: [(); 1 - {
+LL | |         trait NotCopy {
+LL | |             const VALUE: bool = false;
+LL | |         }
+...  |
+LL | |         <IsCopy<T>>::VALUE
+LL | |     } as usize] = [];
+   | |_____________________^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); 1 - {
+                   trait NotCopy {
+                       const VALUE: bool = false;
+                   }
+           
+                   impl<__Type: ?Sized> NotCopy for __Type {}
+           
+                   struct IsCopy<__Type: ?Sized>(PhantomData<__Type>);
+           
+                   impl<__Type> IsCopy<__Type>
+                   where
+                       __Type: Sized + Copy,
+                   {
+                       const VALUE: bool = true;
+                   }
+           
+                   <IsCopy<T>>::VALUE
+               } as usize]:`
+
+error: aborting due to previous error
+
index f015d6946954f57dc3506401d608d3fb1e8bee21..66f819dbe06e2b378c12985275ed5a49f6d43b57 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Test(*const usize);
index 3a56db937de093befcad095900225a8d1a5fd97d..4392d72e5668e97a93d772f3f30ab3bbcff00ff4 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Test();
index 6468d0b6bdae3fa163ebdc8336c1596a43315dd9..fbb91ca18aa4fd82974d7dc48b66102509a3ee7d 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn func<A, const F: fn(inner: A)>(outer: A) {
index 6bfdba5711ef652a62af4e79c680d8ff36dee1d5..6f0a98ead88704e436fd2480e593a36f97f376c2 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 pub trait Foo<const B: bool> {}
 pub fn bar<T: Foo<{ true }>>() {}
index 9cd95c11026d743e1f6d8d703bbee572cad678b7..2fa1d7a53378304f00a6d70887c1ad3eab556524 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 use std::ffi::{CStr, CString};
diff --git a/src/test/ui/const-generics/issues/issue-72787.full.stderr b/src/test/ui/const-generics/issues/issue-72787.full.stderr
deleted file mode 100644 (file)
index fbb7ae5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72787.rs:10:32
-   |
-LL |     Condition<{ LHS <= RHS }>: True
-   |                                ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72787.rs:25:42
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72787.rs:25:42
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72787.rs:25:42
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72787.rs:25:42
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                          ^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 5 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-72787.min.stderr b/src/test/ui/const-generics/issues/issue-72787.min.stderr
deleted file mode 100644 (file)
index 86d1da0..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:10:17
-   |
-LL |     Condition<{ LHS <= RHS }>: True
-   |                 ^^^ cannot perform const operation using `LHS`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `LHS`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:10:24
-   |
-LL |     Condition<{ LHS <= RHS }>: True
-   |                        ^^^ cannot perform const operation using `RHS`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `RHS`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:25:25
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                         ^ cannot perform const operation using `I`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `I`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-72787.rs:25:36
-   |
-LL |     IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-   |                                    ^ cannot perform const operation using `J`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `J`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error[E0283]: type annotations needed
-  --> $DIR/issue-72787.rs:21:26
-   |
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
-   |
-   = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
-note: required by a bound in `True`
-  --> $DIR/issue-72787.rs:7:1
-   |
-LL | pub trait True {}
-   | ^^^^^^^^^^^^^^ required by this bound in `True`
-
-error[E0283]: type annotations needed
-  --> $DIR/issue-72787.rs:21:26
-   |
-LL |     IsLessOrEqual<I, 8>: True,
-   |                          ^^^^ cannot infer type for struct `IsLessOrEqual<I, 8_u32>`
-   |
-   = note: cannot satisfy `IsLessOrEqual<I, 8_u32>: True`
-note: required by a bound in `True`
-  --> $DIR/issue-72787.rs:7:1
-   |
-LL | pub trait True {}
-   | ^^^^^^^^^^^^^^ required by this bound in `True`
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/const-generics/issues/issue-72787.rs b/src/test/ui/const-generics/issues/issue-72787.rs
deleted file mode 100644 (file)
index 16bc947..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub struct IsLessOrEqual<const LHS: u32, const RHS: u32>;
-pub struct Condition<const CONDITION: bool>;
-pub trait True {}
-
-impl<const LHS: u32, const RHS: u32> True for IsLessOrEqual<LHS, RHS> where
-    Condition<{ LHS <= RHS }>: True
-//[full]~^ Error constant expression depends on a generic parameter
-//[min]~^^ Error generic parameters may not be used in const operations
-//[min]~| Error generic parameters may not be used in const operations
-{
-}
-impl True for Condition<true> {}
-
-struct S<const I: u32, const J: u32>;
-impl<const I: u32, const J: u32> S<I, J>
-where
-    IsLessOrEqual<I, 8>: True,
-//[min]~^ Error type annotations needed [E0283]
-//[min]~| Error type annotations needed [E0283]
-    IsLessOrEqual<J, 8>: True,
-    IsLessOrEqual<{ 8 - I }, { 8 - J }>: True,
-//[full]~^ constant expression depends on a generic parameter
-//[full]~| constant expression depends on a generic parameter
-//[full]~| constant expression depends on a generic parameter
-//[full]~| constant expression depends on a generic parameter
-//[min]~^^^^^ Error generic parameters may not be used in const operations
-//[min]~| Error generic parameters may not be used in const operations
-    // Condition<{ 8 - I <= 8 - J }>: True,
-{
-    fn print() {
-        println!("I {} J {}", I, J);
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.full.stderr
deleted file mode 100644 (file)
index 82f9b9d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-72819-generic-in-const-eval.rs:8:39
-   |
-LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
-   |                                       ^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.min.stderr
deleted file mode 100644 (file)
index 6646be4..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-72819-generic-in-const-eval.rs:8:17
-   |
-LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
-   |                 ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs
deleted file mode 100644 (file)
index f612d8b..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type
-// bounds.
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-struct Arr<const N: usize>
-where Assert::<{N < usize::MAX / 2}>: IsTrue,
-//[full]~^ ERROR constant expression depends on a generic parameter
-//[min]~^^ ERROR generic parameters may not be used in const operations
-{
-}
-
-enum Assert<const CHECK: bool> {}
-
-trait IsTrue {}
-
-impl IsTrue for Assert<true> {}
-
-fn main() {
-    let x: Arr<{usize::MAX}> = Arr {};
-}
index c153a93cdef4f002c065fd2f9d5320a56c3c0b1d..050dc9bde64b020b0c7f5bad143aef15fbe1073d 100644 (file)
@@ -1,6 +1,7 @@
-// revisions: full min
 // check-pass
 // aux-build:const_generic_issues_lib.rs
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
 extern crate const_generic_issues_lib as lib2;
 fn unused_function(
     _: <lib2::GenericType<42> as lib2::TypeFn>::Output
index 04e4e9cd52b0063608dc8c912c4bcdafd81b732b..d762f9c8b2620c1629bd917a5f049a0e7afffb62 100644 (file)
@@ -1,11 +1,10 @@
 // compile-flags: -Zsave-analysis
-
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 struct Arr<const N: usize>
-where Assert::<{N < usize::MAX / 2}>: IsTrue, //~ ERROR constant expression
-{
-}
+where
+    Assert::<{N < usize::MAX / 2}>: IsTrue,
+{}
 
 enum Assert<const CHECK: bool> {}
 
index 6a912ffc3c01bd112ca2b1185b88f83a8cc68d01..f1fc50e6e591446526fc66ce47c162b91b523008 100644 (file)
@@ -1,13 +1,5 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-73260.rs:6:39
-   |
-LL | where Assert::<{N < usize::MAX / 2}>: IsTrue,
-   |                                       ^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
 error[E0308]: mismatched types
-  --> $DIR/issue-73260.rs:17:12
+  --> $DIR/issue-73260.rs:16:12
    |
 LL |     let x: Arr<{usize::MAX}> = Arr {};
    |            ^^^^^^^^^^^^^^^^^ expected `false`, found `true`
@@ -16,7 +8,7 @@ LL |     let x: Arr<{usize::MAX}> = Arr {};
               found type `true`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-73260.rs:17:32
+  --> $DIR/issue-73260.rs:16:32
    |
 LL |     let x: Arr<{usize::MAX}> = Arr {};
    |                                ^^^ expected `false`, found `true`
@@ -24,6 +16,6 @@ LL |     let x: Arr<{usize::MAX}> = Arr {};
    = note: expected type `false`
               found type `true`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index c8f2e0dadc1a7cb2f9d9fdb6bd7f95668bcec8d4..f2b58e59f731fd2df847a8ad008ded45c5f946f2 100644 (file)
@@ -5,7 +5,7 @@ LL | fn hoge<const IN: [u32; LEN]>() {}
    |                   ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index c7cb92baf30aa47a2c74d60b95408c771b23d44e..f15c1f2d4552181e2c18d2396fa2993b58007094 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 const LEN: usize = 1024;
diff --git a/src/test/ui/const-generics/issues/issue-73508.full.stderr b/src/test/ui/const-generics/issues/issue-73508.full.stderr
deleted file mode 100644 (file)
index 81691a1..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/issue-73508.rs:5:33
-   |
-LL | pub const fn func_name<const X: *const u32>() {}
-   |                                 ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-73508.min.stderr b/src/test/ui/const-generics/issues/issue-73508.min.stderr
deleted file mode 100644 (file)
index 81691a1..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: using raw pointers as const generic parameters is forbidden
-  --> $DIR/issue-73508.rs:5:33
-   |
-LL | pub const fn func_name<const X: *const u32>() {}
-   |                                 ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/issues/issue-73508.rs b/src/test/ui/const-generics/issues/issue-73508.rs
deleted file mode 100644 (file)
index f02c416..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub const fn func_name<const X: *const u32>() {}
-//~^ ERROR using raw pointers
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-73899.rs b/src/test/ui/const-generics/issues/issue-73899.rs
deleted file mode 100644 (file)
index 2a3a5ab..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-#![feature(const_evaluatable_checked)]
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
-trait Foo {}
-
-impl<const N: usize> Foo for [(); N] where Self: FooImpl<{ N == 0 }> {}
-
-trait FooImpl<const IS_ZERO: bool> {}
-
-impl FooImpl<{ 0u8 == 0u8 }> for [(); 0] {}
-
-impl<const N: usize> FooImpl<{ 0u8 != 0u8 }> for [(); N] {}
-
-fn foo<T: Foo>(_v: T) {}
-
-fn main() {
-    foo([]);
-    foo([()]);
-}
index a7f0ecf0a2692f2ebc2c2e369877cd6d0fd7851e..82ffb2332404496ac404b15703266a2b3feae8fb 100644 (file)
@@ -5,7 +5,7 @@ LL | fn test<const N: [u8; 1 + 2]>() {}
    |                  ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74101.rs:9:21
@@ -14,7 +14,7 @@ LL | struct Foo<const N: [u8; 1 + 2]>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index d4fd72eb6daa3b787d1c5bfe32df9cba16a58892..6b606b9460fe22f95afc7d30e03488c213da00ee 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn test<const N: [u8; 1 + 2]>() {}
index 62ad43974f4d8978c1dd4e02a374388bcc7c2d61..b462d84487ee8ffeb20a722a19d821419a78a433 100644 (file)
@@ -5,7 +5,7 @@ LL |     fn ice_struct_fn<const I: IceEnum>() {}
    |                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index 75a876c27e59de24f943fdf0978aafe187666af0..0e523926fb0b107e133a92bd64999c090b89b46d 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 #[derive(PartialEq, Eq)]
diff --git a/src/test/ui/const-generics/issues/issue-74634.rs b/src/test/ui/const-generics/issues/issue-74634.rs
deleted file mode 100644 (file)
index 0f23fa9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
-trait If<const COND: bool> {}
-impl If<true> for () {}
-
-trait IsZero<const N: u8> {
-    type Answer;
-}
-
-struct True;
-struct False;
-
-impl<const N: u8> IsZero<N> for ()
-where (): If<{N == 0}> { //~ERROR constant expression
-    type Answer = True;
-}
-
-trait Foobar<const N: u8> {}
-
-impl<const N: u8> Foobar<N> for ()
-where (): IsZero<N, Answer = True> {}
-
-impl<const N: u8> Foobar<N> for ()
-where (): IsZero<N, Answer = False> {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-74634.stderr b/src/test/ui/const-generics/issues/issue-74634.stderr
deleted file mode 100644 (file)
index 091a1ac..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-74634.rs:15:11
-   |
-LL | where (): If<{N == 0}> {
-   |           ^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error
-
index dc3c33736dabfc81b90fa07e856ea461dad89fdf..cc1f2853fb2af32467f6eb1359b071f7200a55b1 100644 (file)
@@ -1,8 +1,6 @@
 // edition:2018
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+
 
 const SIZE: usize = 16;
 
index 4e640ff857eae71b7ae9c2314b3a777297da1ed1..729ecc2022c9927c8bc3d6722c8ff0a7dbb16fd8 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -14,7 +14,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -23,7 +23,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -32,7 +32,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -41,7 +41,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 5 previous errors
 
index 91e5cc776facf0c50122356dbcbee1f58b7b4990..3e1ca4735db612ee0887fb128da6ee9fc47a32aa 100644 (file)
@@ -1,6 +1,6 @@
 // [full] build-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 
index 3c1c3ea97b540231901213dbfed75e9ffc757e86..7798ae7962983047f91dcb06498886a96467eebd 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; Bar::<u32>::value()]>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index 97437748177e45eb6326235d01beddcec5f4065e..ee3dcf9ecec508fa9af1349197dba1f0f86f7ebc 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Bar<T>(T);
index 9d3f25b3b47f8a5b7ee9ea670254f58333ce1fc5..83ef09af88e3b413343c3245b9f81aa43eac5c59 100644 (file)
@@ -1,8 +1,5 @@
 // compile-flags: -Zmir-opt-level=4
 // run-pass
-
-#![feature(const_generics)]
-#![allow(incomplete_features)]
 fn main() {
     fn foo<const N: usize>() -> [u8; N] {
         [0; N]
index c311de05a1cff1c4e6bcfea32053ad516217c6b7..214a04b8a6bed5786e5c28951a038dea9063f1a7 100644 (file)
@@ -1,15 +1,15 @@
 // ignore-test
 // FIXME(const_generics): This test causes an ICE after reverting #76030.
-
+#![feature(adt_const_params)]
 #![allow(incomplete_features)]
-#![feature(const_generics)]
+
 
 struct Bug<const S: &'static str>;
 
 fn main() {
     let b: Bug::<{
         unsafe {
-            // FIXME(const_generics): Decide on how to deal with invalid values as const params.
+            // FIXME(adt_const_params): Decide on how to deal with invalid values as const params.
             std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5])
         }
     }>;
diff --git a/src/test/ui/const-generics/issues/issue-76595.rs b/src/test/ui/const-generics/issues/issue-76595.rs
deleted file mode 100644 (file)
index 2d7051c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-struct Bool<const B: bool>;
-
-trait True {}
-
-impl True for Bool<true> {}
-
-fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
-    todo!()
-}
-
-fn main() {
-    test::<2>();
-    //~^ ERROR this function takes 2 generic arguments
-}
diff --git a/src/test/ui/const-generics/issues/issue-76595.stderr b/src/test/ui/const-generics/issues/issue-76595.stderr
deleted file mode 100644 (file)
index 3b69a40..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
-  --> $DIR/issue-76595.rs:15:5
-   |
-LL |     test::<2>();
-   |     ^^^^   - supplied 1 generic argument
-   |     |
-   |     expected 2 generic arguments
-   |
-note: function defined here, with 2 generic parameters: `T`, `P`
-  --> $DIR/issue-76595.rs:10:4
-   |
-LL | fn test<T, const P: usize>() where Bool<{core::mem::size_of::<T>() > 4}>: True {
-   |    ^^^^ -        -
-help: add missing generic argument
-   |
-LL |     test::<2, P>();
-   |             +++
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.full.stderr
deleted file mode 100644 (file)
index 88b8ff8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-76701-ty-param-in-const.rs:5:21
-   |
-LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-76701-ty-param-in-const.rs:11:37
-   |
-LL | fn const_param<const N: usize>() -> [u8; N + 1] {
-   |                                     ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.min.stderr
deleted file mode 100644 (file)
index 32f70fa..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-76701-ty-param-in-const.rs:5:46
-   |
-LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
-   |                                              ^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/issue-76701-ty-param-in-const.rs:11:42
-   |
-LL | fn const_param<const N: usize>() -> [u8; N + 1] {
-   |                                          ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
index 9948982656357ace8b115c758f8f876e5ca9dfb0..2e6b0223656a78bdc676f4f8a9b50c03936a264e 100644 (file)
@@ -1,16 +1,10 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
+    //~^ ERROR generic parameters may not be used in const operations
     todo!()
 }
 
 fn const_param<const N: usize>() -> [u8; N + 1] {
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
+    //~^ ERROR generic parameters may not be used in const operations
     todo!()
 }
 
diff --git a/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr b/src/test/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr
new file mode 100644 (file)
index 0000000..3b53e18
--- /dev/null
@@ -0,0 +1,20 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-76701-ty-param-in-const.rs:1:46
+   |
+LL | fn ty_param<T>() -> [u8; std::mem::size_of::<T>()] {
+   |                                              ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/issue-76701-ty-param-in-const.rs:6:42
+   |
+LL | fn const_param<const N: usize>() -> [u8; N + 1] {
+   |                                          ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.rs
deleted file mode 100644 (file)
index 8f02bfb..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This test is a minimized reproduction for #79518 where
-// during error handling for the type mismatch we would try
-// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
-
-trait Foo {
-    type Assoc: PartialEq;
-    const AssocInstance: Self::Assoc;
-
-    fn foo()
-    where
-        [(); std::mem::size_of::<Self::Assoc>()]: ,
-    {
-        Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-        //~^ Error: mismatched types
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/issues/issue-79518-default_trait_method_normalization.stderr
deleted file mode 100644 (file)
index c90774e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
-   |
-LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
-   |
-   = note: expected associated type `<Self as Foo>::Assoc`
-                        found array `[(); _]`
-   = help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
index aad8907bda2d0cf8d5ebf63cf418686835738179..754f18d5cc4200820d213209ad3e067f26e11305 100644 (file)
@@ -5,7 +5,7 @@ LL |     let _: [u8; sof::<T>()];
    |                       ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 9765a639a48d09ee9351cd6165829b05a6874f55..5409002a9fdeb95664947dc7eeac6d4034c72136 100644 (file)
@@ -5,7 +5,7 @@ LL | struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
    |                                         ^^^^^ cannot perform const operation using `COUNT`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `COUNT`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs b/src/test/ui/const-generics/issues/issue-80561-incorrect-param-env.rs
deleted file mode 100644 (file)
index a34d74b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-// This tests that the correct `param_env` is used so that
-// attempting to normalize `Self::N` does not cause an ICE.
-
-pub struct Foo<const N: usize>;
-
-impl<const N: usize> Foo<N> {
-    pub fn foo() {}
-}
-
-pub trait Bar {
-    const N: usize;
-    fn bar()
-    where
-        [(); Self::N]: ,
-    {
-        Foo::<{ Self::N }>::foo();
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-82956.rs b/src/test/ui/const-generics/issues/issue-82956.rs
new file mode 100644 (file)
index 0000000..a3a0d8d
--- /dev/null
@@ -0,0 +1,33 @@
+#![feature(generic_const_exprs, array_map)]
+#![allow(incomplete_features)]
+
+pub struct ConstCheck<const CHECK: bool>;
+
+pub trait True {}
+impl True for ConstCheck<true> {}
+
+pub trait OrdesDec {
+    type Newlen;
+    type Output;
+
+    fn pop(self) -> (Self::Newlen, Self::Output);
+}
+
+impl<T, const N: usize> OrdesDec for [T; N]
+where
+    ConstCheck<{N > 1}>: True,
+    [T; N - 1]: Sized,
+{
+    type Newlen = [T; N - 1];
+    type Output = T;
+
+    fn pop(self) -> (Self::Newlen, Self::Output) {
+        let mut iter = IntoIter::new(self);
+        //~^ ERROR: failed to resolve: use of undeclared type `IntoIter`
+        let end = iter.next_back().unwrap();
+        let new = [(); N - 1].map(move |()| iter.next().unwrap());
+        (new, end)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-82956.stderr b/src/test/ui/const-generics/issues/issue-82956.stderr
new file mode 100644 (file)
index 0000000..c8b999d
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0433]: failed to resolve: use of undeclared type `IntoIter`
+  --> $DIR/issue-82956.rs:25:24
+   |
+LL |         let mut iter = IntoIter::new(self);
+   |                        ^^^^^^^^ not found in this scope
+   |
+help: consider importing one of these items
+   |
+LL | use std::array::IntoIter;
+   |
+LL | use std::collections::binary_heap::IntoIter;
+   |
+LL | use std::collections::btree_map::IntoIter;
+   |
+LL | use std::collections::btree_set::IntoIter;
+   |
+     and 8 other candidates
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs
deleted file mode 100644 (file)
index f34badc..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait TensorDimension {
-    const DIM: usize;
-}
-
-trait TensorSize: TensorDimension {
-    fn size(&self) -> [usize; Self::DIM];
-}
-
-trait Broadcastable: TensorSize + Sized {
-    type Element;
-    fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {}
-}
-
-struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
-    reference: &'a T,
-    closure: F,
-}
-
-impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
-    for BMap<'a, R, T, F, DIM>
-{
-    const DIM: usize = DIM;
-}
-impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
-    for BMap<'a, R, T, F, DIM>
-{
-    fn size(&self) -> [usize; DIM] {
-        //~^ ERROR: method not compatible with trait [E0308]
-        self.reference.size()
-        //~^ ERROR: unconstrained generic constant
-        //~| ERROR: mismatched types
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
deleted file mode 100644 (file)
index ef785bf..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-error[E0308]: method not compatible with trait
-  --> $DIR/issue-83765.rs:30:5
-   |
-LL |     fn size(&self) -> [usize; DIM] {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
-   |
-   = note: expected type `Self::DIM`
-              found type `DIM`
-
-error: unconstrained generic constant
-  --> $DIR/issue-83765.rs:32:24
-   |
-LL |         self.reference.size()
-   |                        ^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-83765.rs:32:9
-   |
-LL |         self.reference.size()
-   |         ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
-   |
-   = note: expected type `DIM`
-              found type `Self::DIM`
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/const-generics/issues/issue-84408.rs b/src/test/ui/const-generics/issues/issue-84408.rs
deleted file mode 100644 (file)
index e1ba850..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Regression test for #84408.
-// check-pass
-
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait Melon<const X: usize> {
-    fn new(arr: [i32; X]) -> Self;
-    fn change<T: Melon<X>>(self) -> T;
-}
-
-struct Foo([i32; 5]);
-struct Bar<const A: usize, const B: usize>([i32; A + B])
-where
-    [(); A + B]: ;
-
-impl Melon<5> for Foo {
-    fn new(arr: [i32; 5]) -> Self {
-        Foo(arr)
-    }
-    fn change<T: Melon<5>>(self) -> T {
-        T::new(self.0)
-    }
-}
-
-impl<const A: usize, const B: usize> Melon<{ A + B }> for Bar<A, B>
-where
-    [(); A + B]: ,
-{
-    fn new(arr: [i32; A + B]) -> Self {
-        Bar(arr)
-    }
-    fn change<T: Melon<{ A + B }>>(self) -> T {
-        T::new(self.0)
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-84659.rs b/src/test/ui/const-generics/issues/issue-84659.rs
new file mode 100644 (file)
index 0000000..440ca74
--- /dev/null
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+
+trait Bar<const N: usize> {}
+
+trait Foo<'a> {
+    const N: usize;
+    type Baz: Bar<{ Self::N }>;
+    //~^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-84659.stderr b/src/test/ui/const-generics/issues/issue-84659.stderr
new file mode 100644 (file)
index 0000000..2dfc48a
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/issue-84659.rs:8:15
+   |
+LL |     type Baz: Bar<{ Self::N }>;
+   |               ^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { Self::N }]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs
deleted file mode 100644 (file)
index 4787198..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-trait _Contains<T> {
-    const does_contain: bool;
-}
-
-trait Contains<T, const Satisfied: bool> {}
-
-trait Delegates<T> {}
-
-impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
-
-const fn contains<A, B>() -> bool
-where
-    A: _Contains<B>,
-{
-    A::does_contain
-}
-
-impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
-
-fn writes_to_path<C>(cap: &C) {
-    writes_to_specific_path(&cap);
-    //~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277]
-    //~| ERROR: unconstrained generic constant
-}
-
-fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr
deleted file mode 100644 (file)
index e51db35..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
-  --> $DIR/issue-85848.rs:24:5
-   |
-LL |     writes_to_specific_path(&cap);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
-   |
-note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
-  --> $DIR/issue-85848.rs:21:12
-   |
-LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required because of the requirements on the impl of `Delegates<()>` for `&C`
-  --> $DIR/issue-85848.rs:12:12
-   |
-LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
-   |            ^^^^^^^^^^^^     ^
-note: required by a bound in `writes_to_specific_path`
-  --> $DIR/issue-85848.rs:29:31
-   |
-LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
-   |                               ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path`
-
-error: unconstrained generic constant
-  --> $DIR/issue-85848.rs:24:5
-   |
-LL |     writes_to_specific_path(&cap);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
-note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
-  --> $DIR/issue-85848.rs:21:12
-   |
-LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required because of the requirements on the impl of `Delegates<()>` for `&C`
-  --> $DIR/issue-85848.rs:12:12
-   |
-LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
-   |            ^^^^^^^^^^^^     ^
-note: required by a bound in `writes_to_specific_path`
-  --> $DIR/issue-85848.rs:29:31
-   |
-LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
-   |                               ^^^^^^^^^^^^^ required by this bound in `writes_to_specific_path`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-86530.rs b/src/test/ui/const-generics/issues/issue-86530.rs
new file mode 100644 (file)
index 0000000..b024dec
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait X {
+    const Y: usize;
+}
+
+fn z<T>(t: T)
+where
+    T: X,
+    [(); T::Y]: ,
+{
+}
+
+fn unit_literals() {
+    z(" ");
+    //~^ ERROR: the trait bound `&str: X` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86530.stderr b/src/test/ui/const-generics/issues/issue-86530.stderr
new file mode 100644 (file)
index 0000000..7cdfc9d
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `&str: X` is not satisfied
+  --> $DIR/issue-86530.rs:16:7
+   |
+LL |     z(" ");
+   |       ^^^ the trait `X` is not implemented for `&str`
+   |
+note: required by a bound in `z`
+  --> $DIR/issue-86530.rs:10:8
+   |
+LL | fn z<T>(t: T)
+   |    - required by a bound in this
+LL | where
+LL |     T: X,
+   |        ^ required by this bound in `z`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-86535-2.rs b/src/test/ui/const-generics/issues/issue-86535-2.rs
new file mode 100644 (file)
index 0000000..0b535fd
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+    const ASSOC_C: usize;
+    fn foo() where [(); Self::ASSOC_C]:;
+}
+
+struct Bar<const N: &'static ()>;
+impl<const N: &'static ()> Foo for Bar<N> {
+    const ASSOC_C: usize = 3;
+
+    fn foo() where [u8; Self::ASSOC_C]: {
+        let _: [u8; Self::ASSOC_C] = loop {};
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-86535.rs b/src/test/ui/const-generics/issues/issue-86535.rs
new file mode 100644 (file)
index 0000000..5289c4e
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+#![feature(adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features, unused_variables)]
+
+struct F<const S: &'static str>;
+impl<const S: &'static str> X for F<{ S }> {
+    const W: usize = 3;
+
+    fn d(r: &[u8; Self::W]) -> F<{ S }> {
+        let x: [u8; Self::W] = [0; Self::W];
+        F
+    }
+}
+
+pub trait X {
+    const W: usize;
+    fn d(r: &[u8; Self::W]) -> Self;
+}
+
+fn main() {}
index 5dfda943bf69c3f0cf2cf177f7027918155e1af5..8a567678b824e34d615830db87dd381c17337ddf 100644 (file)
@@ -1,6 +1,6 @@
 // build-pass
 
-#![feature(const_generics)]
+#![feature(adt_const_params)]
 #![allow(incomplete_features)]
 
 #[derive(PartialEq, Eq)]
index 0aaeaffb4cb9db43a0459a46fb56378cb5c86ca8..5294cc3b5f42e1eca8917da1d8a6873367214885 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 const fn inner<'a>() -> usize where &'a (): Sized {
index 2c411a3bdc5f36cd2273f535202c4611a35fe7c0..6da5395ef83ce28206d0e6e8c4a6f8a76c50275f 100644 (file)
@@ -1,5 +1,5 @@
 // run-pass
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 const fn inner<'a>() -> usize where &'a (): Sized {
diff --git a/src/test/ui/const-generics/macro_rules-braces.full.stderr b/src/test/ui/const-generics/macro_rules-braces.full.stderr
deleted file mode 100644 (file)
index b29e853..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:48:17
-   |
-LL |     let _: baz!(m::P);
-   |                 ^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     let _: baz!({ m::P });
-   |                 +      +
-
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:68:17
-   |
-LL |     let _: baz!(10 + 7);
-   |                 ^^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     let _: baz!({ 10 + 7 });
-   |                 +        +
-
-error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:15:13
-   |
-LL |             [u8; $x]
-   |             ^^^^^^^^
-...
-LL |     let _: foo!({{ N }});
-   |            ------------- in this macro invocation
-   |
-   = note: this may fail depending on what value the parameter takes
-   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:20:13
-   |
-LL |             [u8; { $x }]
-   |             ^^^^^^^^^^^^
-...
-LL |     let _: bar!({ N });
-   |            ----------- in this macro invocation
-   |
-   = note: this may fail depending on what value the parameter takes
-   = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:25:13
-   |
-LL |             Foo<$x>
-   |             ^^^^^^^
-...
-LL |     let _: baz!({{ N }});
-   |            ------------- in this macro invocation
-   |
-   = note: this may fail depending on what value the parameter takes
-   = note: this error originates in the macro `baz` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: constant expression depends on a generic parameter
-  --> $DIR/macro_rules-braces.rs:30:13
-   |
-LL |             Foo<{ $x }>
-   |             ^^^^^^^^^^^
-...
-LL |     let _: biz!({ N });
-   |            ----------- in this macro invocation
-   |
-   = note: this may fail depending on what value the parameter takes
-   = note: this error originates in the macro `biz` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/const-generics/macro_rules-braces.min.stderr b/src/test/ui/const-generics/macro_rules-braces.min.stderr
deleted file mode 100644 (file)
index c2e8c2c..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:48:17
-   |
-LL |     let _: baz!(m::P);
-   |                 ^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     let _: baz!({ m::P });
-   |                 +      +
-
-error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/macro_rules-braces.rs:68:17
-   |
-LL |     let _: baz!(10 + 7);
-   |                 ^^^^^^
-   |
-help: enclose the `const` expression in braces
-   |
-LL |     let _: baz!({ 10 + 7 });
-   |                 +        +
-
-error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:36:20
-   |
-LL |     let _: foo!({{ N }});
-   |                    ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:40:19
-   |
-LL |     let _: bar!({ N });
-   |                   ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:45:20
-   |
-LL |     let _: baz!({{ N }});
-   |                    ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/macro_rules-braces.rs:50:19
-   |
-LL |     let _: biz!({ N });
-   |                   ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/const-generics/macro_rules-braces.rs b/src/test/ui/const-generics/macro_rules-braces.rs
deleted file mode 100644 (file)
index 605a108..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-// revisions: full min
-#![cfg_attr(full, allow(incomplete_features))]
-#![cfg_attr(full, feature(const_generics))]
-
-mod m {
-    pub const P: usize = 0;
-}
-
-const Q: usize = 0;
-
-fn test<const N: usize>() {
-    struct Foo<const M: usize>;
-    macro_rules! foo {
-        ($x:expr) => {
-            [u8; $x] //[full]~ ERROR constant expression depends
-        }
-    }
-    macro_rules! bar {
-        ($x:expr) => {
-            [u8; { $x }] //[full]~ ERROR constant expression depends
-        }
-    }
-    macro_rules! baz {
-        ( $x:expr) => {
-            Foo<$x> //[full]~ ERROR constant expression depends
-        }
-    }
-    macro_rules! biz {
-        ($x:expr) => {
-            Foo<{ $x }> //[full]~ ERROR constant expression depends
-        };
-    }
-
-    let _: foo!(N);
-    let _: foo!({ N });
-    let _: foo!({{ N }}); //[min]~ ERROR generic parameters may not
-    let _: foo!(Q);
-    let _: foo!(m::P);
-    let _: bar!(N);
-    let _: bar!({ N }); //[min]~ ERROR generic parameters may not
-    let _: bar!(Q);
-    let _: bar!(m::P);
-    let _: baz!(N);
-    let _: baz!({ N });
-    let _: baz!({{ N }}); //[min]~ ERROR generic parameters may not
-    let _: baz!(Q);
-    let _: baz!({ m::P });
-    let _: baz!(m::P); //~ ERROR expressions must be enclosed in braces
-    let _: biz!(N);
-    let _: biz!({ N }); //[min]~ ERROR generic parameters may not
-    let _: biz!(Q);
-    let _: biz!(m::P);
-    let _: foo!(3);
-    let _: foo!({ 3 });
-    let _: foo!({{ 3 }});
-    let _: bar!(3);
-    let _: bar!({ 3 });
-    let _: baz!(3);
-    let _: baz!({ 3 });
-    let _: baz!({{ 3 }});
-    let _: biz!(3);
-    let _: biz!({ 3 });
-    let _: foo!(10 + 7);
-    let _: foo!({ 10 + 7 });
-    let _: foo!({{ 10 + 7 }});
-    let _: bar!(10 + 7);
-    let _: bar!({ 10 + 7 });
-    let _: baz!(10 + 7); //~ ERROR expressions must be enclosed in braces
-    let _: baz!({ 10 + 7 });
-    let _: baz!({{ 10 + 7 }});
-    let _: biz!(10 + 7);
-    let _: biz!({ 10 + 7 });
-}
-
-fn main() {
-    test::<3>();
-}
index 176692448491aaa0a4a3c0967808a45c391a5c9d..bf0d0f352ebc43a17e5c07bcf0c24ea69b2c7f77 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Break0<const N: usize>([u8; { N + 1 }]);
    |                                      ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:12:40
@@ -14,7 +14,7 @@ LL | struct Break1<const N: usize>([u8; { { N } }]);
    |                                        ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:16:17
@@ -23,7 +23,7 @@ LL |     let _: [u8; N + 1];
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:21:17
@@ -32,7 +32,7 @@ LL |     let _ = [0; N + 1];
    |                 ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:25:45
@@ -41,7 +41,7 @@ LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
    |                                             ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:28:47
@@ -50,7 +50,7 @@ LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
    |                                               ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic parameters may not be used in const operations
   --> $DIR/complex-expression.rs:32:32
@@ -59,7 +59,7 @@ LL |     let _: [u8; size_of::<*mut T>() + 1];
    |                                ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 warning: cannot use constants which depend on generic parameters in types
   --> $DIR/complex-expression.rs:37:17
index a658a7b3956896a408a46b69df6d55da2171e4c8..4ddbadb54661b22031bdc536036699f49448bc28 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; 0]>;
    |                     ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:6:21
@@ -14,7 +14,7 @@ LL | struct Bar<const N: ()>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `No` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:11:21
@@ -23,7 +23,7 @@ LL | struct Fez<const N: No>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:14:21
@@ -32,7 +32,7 @@ LL | struct Faz<const N: &'static u8>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `!` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:17:21
@@ -41,7 +41,7 @@ LL | struct Fiz<const N: !>;
    |                     ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:20:19
@@ -50,7 +50,7 @@ LL | enum Goo<const N: ()> { A, B }
    |                   ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:23:20
@@ -59,7 +59,7 @@ LL | union Boo<const N: ()> { a: () }
    |                    ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 7 previous errors
 
index ae82c85eb7e4be6031348c389cd4ec5937af50af..bba4e68d4cce54c77999693b6f4063b6674070a3 100644 (file)
@@ -1,5 +1,4 @@
 #![crate_type = "lib"]
-#![feature(const_generics)]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features, dead_code)]
 
index f7a2e484fc61bcbcb5e709cbded0e1850004215e..1a333642f0c3cb166d660b47ff54be24e20e45fc 100644 (file)
@@ -1,5 +1,5 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/const_default_first.rs:6:19
+  --> $DIR/const_default_first.rs:5:19
    |
 LL | struct Both<const N: usize=3, T> {
    |                   ^
index 881f8b98aad086bb870e19068b0aa1bcd1849ca7..6215b7d936cfd9736a1b52845f707facfb01c4f6 100644 (file)
@@ -1,5 +1,5 @@
 // This test checks that non-static lifetimes are prohibited under `min_const_generics`. It
-// currently emits an error with `min_const_generics`. This will ICE under `const_generics`.
+// currently emits an error with `min_const_generics`.
 
 fn test<const N: usize>() {}
 
index 5def54ca26d978dff81e7bb13d456aa0eb0313d8..5f641b0709518341393212b336ea9a1f676ab9df 100644 (file)
@@ -4,8 +4,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     test::<{ let _: &'a (); 3 },>();
    |                      ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error[E0658]: a non-static lifetime is not allowed in a `const`
   --> $DIR/forbid-non-static-lifetimes.rs:21:16
@@ -13,8 +13,8 @@ error[E0658]: a non-static lifetime is not allowed in a `const`
 LL |     [(); (|_: &'a u8| (), 0).1];
    |                ^^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = help: add `#![feature(generic_const_exprs)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
index 4fdfb5fbcb1a76eaa739584cb08f6bc132e4a46f..16a7687c00b54ec5c5f2f7eee23a3ab6737a8d88 100644 (file)
@@ -5,7 +5,7 @@ LL |     fn t1() -> [u8; std::mem::size_of::<Self>()];
    |                                         ^^^^ cannot perform const operation using `Self`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: generic `Self` types are currently not permitted in anonymous constants
   --> $DIR/self-ty-in-const-1.rs:12:41
index 647ef5400cb29bb7f403bbaba848699619965c06..f30693221a513347368bde10aba8e3093c42b8bc 100644 (file)
@@ -5,7 +5,7 @@ LL | fn a<const X: &'static [u32]>() {}
    |               ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index 435a63a5283457a576e99abdf381fa60a8464e31..2adfa9a8c4be28c5e93fd88d71ebdf4536fd76a1 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
-#![feature(const_generics)]
 #![feature(const_generics_defaults)]
-#![allow(incomplete_features, dead_code)]
+#![allow(dead_code)]
 
 struct Both<T=u32, const N: usize=3> {
   arr: [T; N]
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs
deleted file mode 100644 (file)
index 6a5739d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-
-use std::ops::AddAssign;
-
-fn inc<T: AddAssign + Clone, const N: usize>(v: &mut [T; N]) -> &mut [T; N] {
-    for x in v.iter_mut() {
-        *x += x.clone();
-    }
-    v
-}
-
-fn main() {
-    let mut v = [1, 2, 3];
-    inc(&mut v);
-    assert_eq!(v, [2, 4, 6]);
-}
index 6defd393ba068da794e3c6ceeebd8602b29ae0c4..4f32284ecb1e0571ffc5a9f32e046c35e8a63452 100644 (file)
@@ -12,7 +12,7 @@ LL | | }]>;
    | |__^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
   --> $DIR/nested-type.rs:15:5
index be8ebb7f401f276c545cc1fd28e37f6faa3195bf..039f996de96db2c66028ec44250158dcc9ef9635 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
index 68d186500098d481d5c293db203b4196d53e2c1d..ee4244051a1edf19fc9b920c502d4070a7a73054 100644 (file)
@@ -1,5 +1,5 @@
 // build-pass
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // This test does not use any "unevaluated" consts, so it should compile just fine.
index 3cb9b7b9da880867f43943de0eb5be6f1679788d..e6f8e4ad3b3a258841c56de9a8e2e0a54a3cf833 100644 (file)
@@ -1,14 +1,8 @@
-#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
-
-// It depends on how we normalize constants and how const equate works if this
-// compiles.
-//
-// Please ping @lcnr if the output if this test changes.
+// check-pass
+#![feature(generic_const_exprs)] //~ WARN the feature `generic_const_exprs` is incomplete
 
 
 fn bind<const N: usize>(value: [u8; N + 2]) -> [u8; N * 2] {
-    //~^ ERROR constant expression depends on a generic parameter
-    //~| ERROR constant expression depends on a generic parameter
     todo!()
 }
 
index 671f1103dccad7fcfeb56f35c067cb35b5d5ca72..f9b56bd387ae3f0f9c6fa14bc46fab7cc087b505 100644 (file)
@@ -1,27 +1,11 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unify-fixpoint.rs:1:12
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unify-fixpoint.rs:2:12
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
-error: constant expression depends on a generic parameter
-  --> $DIR/unify-fixpoint.rs:9:32
-   |
-LL | fn bind<const N: usize>(value: [u8; N + 2]) -> [u8; N * 2] {
-   |                                ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/unify-fixpoint.rs:9:48
-   |
-LL | fn bind<const N: usize>(value: [u8; N + 2]) -> [u8; N * 2] {
-   |                                                ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
+warning: 1 warning emitted
 
index 552b1b2a66ac523ed8b512b415c2da0c03b94bc3..c6324bca124cd66d0e93328ba78e75dd21ac0cd0 100644 (file)
@@ -1,10 +1,9 @@
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
-// This test would try to unify `N` with `N + 1` which must fail the occurs check.
+// This test would tries to unify `N` with `N + 1` which must fail the occurs check.
 
 fn bind<const N: usize>(value: [u8; N]) -> [u8; N + 1] {
-    //~^ ERROR constant expression depends on a generic parameter
     todo!()
 }
 
@@ -12,6 +11,6 @@
 
 fn main() {
     let mut arr = Default::default();
-    arr = bind(arr);
+    arr = bind(arr); //~ ERROR mismatched types
     sink(arr);
 }
index c1ac7eec1e7d8c912e9802525e9f484cc7cc5d9b..6b8e688fba8d149c84236b156f8d06b028f8d330 100644 (file)
@@ -1,10 +1,9 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/unify-n-nplusone.rs:6:44
+error[E0308]: mismatched types
+  --> $DIR/unify-n-nplusone.rs:14:11
    |
-LL | fn bind<const N: usize>(value: [u8; N]) -> [u8; N + 1] {
-   |                                            ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
+LL |     arr = bind(arr);
+   |           ^^^^^^^^^ encountered a self-referencing constant
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
index 6ded9f13bc4fadacbd90a041e571a7522bdaeb55..9d12250c9143387019307a8726b7fb8d8ae71660 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 trait Bar<const M: usize> {}
index 2d00141fbf70bb1393262a56a7d2e1b76a1d6d60..9a73f1a53e52f10939f699b022be5b0f62f334e1 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // The goal is is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
index 2e306f8c4c88fd46eb1784c962b10d3df9384aa7..0d38bd3935194c04b5c193ba5592b94fca9da99a 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // The goal is is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
index 9c7f5ab91edb13298a6a868b4909ae6f201e6fdf..03c2f54861b431cf19a2eb91d57e30f4cbb4f076 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
index e5d487d89b9f339efdd137888360763949ab6ff8..383ab4cd8c928ddc77085778a462b923129f2cf4 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 // `N + 1` also depends on `T` here even if it doesn't use it.
index e8fd9e7769b791b70195e575b9348912b4bc86fb..9f0b2efae96cef8e13566867259b12e69ebbdbf7 100644 (file)
@@ -3,8 +3,6 @@ error: generic parameters with a default must be trailing
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
 error[E0128]: generic parameters with a default cannot use forward declared identifiers
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
index 5fa6423306c5a5e7cac46e25c983fa404d4d6363..17defbe86aa656a19668b683ea7e93a1c6db0cb0 100644 (file)
@@ -13,7 +13,7 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0128]: generic parameters with a default cannot use forward declared identifiers
   --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
index 76c1b84aef557864846ab7f9695be49113ac3561..b24a7afabd90f0e21a57e09b664c02e61f388606 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
index 31be8e7d111c73f55f6bbd96257a28c268f78b4e..b87e3960fc92ccb8f5ae8f67656d674d9e506c0b 100644 (file)
@@ -1,6 +1,6 @@
 // aux-build:generics_of_parent.rs
 // check-pass
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 extern crate generics_of_parent;
index 988777b1c90c1d31baf6c11882bcc4d3b86acf1b..ed81c01bb1726ee09bf9b74b66d7899baad34aee 100644 (file)
@@ -1,5 +1,5 @@
 // aux-build:generics_of_parent_impl_trait.rs
-#![feature(const_generics, const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 
 extern crate generics_of_parent_impl_trait;
index ca7d33c0eb98496300f9640298aab3db90925d4b..65595f07dab3c40135dea7d943abf4d4854790a9 100644 (file)
@@ -1,7 +1,7 @@
 // Checks that pointers must not be used as the type of const params.
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 const A: u32 = 3;
index a04c6d5e64e1983afe735d761038228bee262d43..27ef9e7d96c9f1c2910d7a08ae71c0554f678ff1 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
index 166a35ee4556efcdef2f8fe3e40fcdfebb17fc8e..fed802f6adc6b82f08406c2fd372a4103237cddb 100644 (file)
@@ -5,7 +5,7 @@ LL | struct ConstString<const T: &'static str>;
    |                             ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param-mismatch.rs:9:28
@@ -14,7 +14,7 @@ LL | struct ConstBytes<const T: &'static [u8]>;
    |                            ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index f020e2bf66fb066a073ec43e1e6429787660b9c9..7127323e5babe25d23bd735425f66d1c21b014b1 100644 (file)
@@ -1,6 +1,6 @@
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 
diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr
deleted file mode 100644 (file)
index ed39a0c..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: `&'static str` is forbidden as the type of a const generic parameter
-  --> $DIR/slice-const-param.rs:7:40
-   |
-LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
-   |                                        ^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: `&'static [u8]` is forbidden as the type of a const generic parameter
-  --> $DIR/slice-const-param.rs:12:41
-   |
-LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
-   |                                         ^^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to 2 previous errors
-
index bf1bf8af9222c424d88b362772417c68191a9804..05d21e08d74538a3d7c418c45cf4dbb72c3f1e43 100644 (file)
@@ -1,16 +1,13 @@
-//[full] run-pass
-// revisions: min full
+// run-pass
 
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(adt_const_params)]
+#![allow(incomplete_features)]
 
 pub fn function_with_str<const STRING: &'static str>() -> &'static str {
-    //[min]~^ ERROR `&'static str` is forbidden
     STRING
 }
 
 pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
-    //[min]~^ ERROR `&'static [u8]` is forbidden
     BYTES
 }
 
diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.rs b/src/test/ui/const-generics/sneaky-array-repeat-expr.rs
new file mode 100644 (file)
index 0000000..b147c24
--- /dev/null
@@ -0,0 +1,32 @@
+trait Trait<const N: usize> {
+    const Assoc: usize;
+}
+
+impl<const N: usize> Trait<N> for () {
+    const Assoc: usize = 1;
+}
+
+
+pub const fn foo<const N: usize>() where (): Trait<N> {
+    let bar = [(); <()>::Assoc];
+    //~^ error: constant expression depends on a generic parameter
+}
+
+trait Trait2<const N: usize> {
+    const Assoc2: usize;
+}
+
+impl<const N: usize> Trait2<N> for () {
+    const Assoc2: usize = N - 1;
+}
+
+
+pub const fn foo2<const N: usize>() where (): Trait2<N> {
+    let bar2 = [(); <()>::Assoc2];
+    //~^ error: constant expression depends on a generic parameter
+}
+
+fn main() {
+    foo::<0>();
+    foo2::<0>();
+}
diff --git a/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr b/src/test/ui/const-generics/sneaky-array-repeat-expr.stderr
new file mode 100644 (file)
index 0000000..5c77375
--- /dev/null
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:11:20
+   |
+LL |     let bar = [(); <()>::Assoc];
+   |                    ^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/sneaky-array-repeat-expr.rs:25:21
+   |
+LL |     let bar2 = [(); <()>::Assoc2];
+   |                     ^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
index 86e6159fdb577e3c23606d08f504916468735d91..d4b2ad6fd0c7bfeb146564dce6e23bee529e2fd3 100644 (file)
@@ -5,7 +5,7 @@ LL | struct _Range<const R: std::ops::Range<usize>>;
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:12:28
@@ -14,7 +14,7 @@ LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `RangeFull` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:17:28
@@ -23,7 +23,7 @@ LL | struct _RangeFull<const R: std::ops::RangeFull>;
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:23:33
@@ -32,7 +32,7 @@ LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `RangeTo<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:28:26
@@ -41,7 +41,7 @@ LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:33:35
@@ -50,7 +50,7 @@ LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 6 previous errors
 
index deaab830e91d30e354cedf3cd5cb6cd8fd4e3739..46c06f312b98fb81eec44844d1cd658389ed6b85 100644 (file)
@@ -1,6 +1,6 @@
 // [full] check-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 // `Range` should be usable within const generics:
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.full.stderr
deleted file mode 100644 (file)
index db99803..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0573]: expected type, found const parameter `C`
-  --> $DIR/struct-with-invalid-const-param.rs:7:23
-   |
-LL | struct S<const C: u8>(C);
-   |                       ^ not a type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0573`.
diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.min.stderr
deleted file mode 100644 (file)
index db99803..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0573]: expected type, found const parameter `C`
-  --> $DIR/struct-with-invalid-const-param.rs:7:23
-   |
-LL | struct S<const C: u8>(C);
-   |                       ^ not a type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0573`.
index 32970ccaa5dbc3d2c2a7067df3867a8753396079..be1c4b0e8e80e61cebe6a8b2c1ed5fdefeab05d5 100644 (file)
@@ -1,8 +1,4 @@
 // Checks that a const param cannot be stored in a struct.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
 
index 47617c7849f4a3d4e8a774208ea4fe910924bfbf..67f497af50503020a002ab0b41c01de2b8674a67 100644 (file)
@@ -1,18 +1,9 @@
 error[E0573]: expected type, found const parameter `C`
-  --> $DIR/struct-with-invalid-const-param.rs:4:23
+  --> $DIR/struct-with-invalid-const-param.rs:3:23
    |
 LL | struct S<const C: u8>(C);
    |                       ^ not a type
 
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/struct-with-invalid-const-param.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0573`.
index 30d05c708e14f3936cbacc00744df8f8964ef95b..2cdef3fb452c86ffd42f7177937174c755155373 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct Const<const N: usize>;
 trait Foo<const N: usize> {}
index f735be9c24e08077af3e6be0f365142b009e595e..039c4276c8b773f2c3dbdf577517cad068079775 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Const<const P: &'static ()>;
    |                       ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to previous error
 
index 3147d61ec9bd9f8c491a3880f6015a4c00585499..6b443c8bd907a13e0560f636033e1c3a7b4387ac 100644 (file)
@@ -1,7 +1,7 @@
 // revisions: full min
 //[full] check-pass
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Const<const P: &'static ()>;
index bf855d4dcaac87d7a7d33e3da12b48ebabd7d477..926e807feb0b4893314a9eb527e5d3ff637d8fa7 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 // revisions: full min
 
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 use std::mem::MaybeUninit;
index 920c067dc1a726fd46da4a74b0bead3b862119eb..68d1940160c458f030b3a26f4bb2c8d03e1666e6 100644 (file)
@@ -1,7 +1,7 @@
 // [full] run-pass
 // revisions: full min
 // Verifies that having generic parameters after constants is permitted
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(const_generics_defaults))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 #[allow(dead_code)]
index cd9c3ae7bbc09ef3521aaf7e99c6d43912c3e181..5dfcbba0e59590ade0da1bb2788affe24e634ad4 100644 (file)
@@ -1,6 +1,3 @@
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 pub struct Struct<const N: usize>(());
 
 impl<const N: usize> Struct<N> {
index 4997d493bbb4a9e1d69afcadbe0a82f3f095e84b..e844148346fb4950155f6c2b53c0e1bfa4f3cd97 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![allow(incomplete_features)]
 
 struct Foo;
index 417fe2501ae3ef1a22961f2f0d9e978d00d894e3..7216b25f0df81b3d3bc6095b483d47c52e61787f 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait SliceExt<T: Clone> {
     fn array_windows_example<'a, const N: usize>(&'a self) -> ArrayWindowsExample<'a, T, N>;
index 2ece25bb41b2c1fedeed4f40bea837ac10bf3b74..08b6d4bf554ad11f823feb00009d3e4e886e6cc7 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait T {
     fn test<const A: i32>(&self) -> i32 { A }
index 4a2c303095e55c6d221c69a391492eb1d7bfcd65..27dd51de2417138b589341cc6deb137753ac919d 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct X;
 
 impl X {
index a1163fca8d4e221fc00c99d5cfaac1608e385e6d..b26f551eb8678311f47eba2b280fa3b95826c8ff 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct A<const N: usize>;
 
 struct X;
index 75ddd839f664d069d39ebc339d4d67539ceec759..cbb6b398e015b3140ec2dc1f259f3f15c09585be 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait IterExt: Sized + Iterator {
     fn default_for_size<const N: usize>(self) -> [Self::Item; N]
     where
index b3585d5fc10753e1e297136765d34f9a3000a4b4..933ca0276098fadd6d6bfd27adb587c659fe5b07 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct Struct<const N: usize>;
 
index df7c277f605baac155341eb896698b0198b62621..c72d9fbec2d8a292dbc6932d0902d6017986e275 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 trait ConstChunksExactTrait<T> {
     fn const_chunks_exact<const N: usize>(&self) -> ConstChunksExact<'_, T, {N}>;
index 5fb571f2394dfa854ee7f269522579e62f4c48aa..346ac4b72cc74f48b1c0ede832db7eb1a86dad9d 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 use std::marker::PhantomData;
 
 // This namespace is necessary for the ICE to trigger
index f3516d1de96bfc08c783ad6cb7c1fe0bef7c7ff0..b8fbb3979799da233cae6eb7a17baa19ef775363 100644 (file)
@@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> {
    |                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/issue-71348.rs:18:25
@@ -14,7 +14,7 @@ LL |     fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
 
 error: aborting due to 2 previous errors
 
index 33735ef87c5a394108a378e93339475c1dbcc24c..2ef2f066a6f6d5e9e55b022b89541d05c3ffb3a6 100644 (file)
@@ -1,6 +1,6 @@
 // [full] run-pass
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(adt_const_params))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo {
diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.full.stderr
deleted file mode 100644 (file)
index 8ac9bab..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71382.rs:16:23
-   |
-LL |     fn test<const FN: fn() -> u8>(&self) -> u8 {
-   |                       ^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.min.stderr
deleted file mode 100644 (file)
index 8ac9bab..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71382.rs:16:23
-   |
-LL |     fn test<const FN: fn() -> u8>(&self) -> u8 {
-   |                       ^^^^^^^^^^
-
-error: aborting due to previous error
-
index b3677613dbc8c7d5ac3795c45f7c1f1096cca084..1c4073e366833f6ed933767cf5c756523748b88e 100644 (file)
@@ -1,7 +1,3 @@
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct Test;
 
 fn pass() -> u8 {
diff --git a/src/test/ui/const-generics/type-dependent/issue-71382.stderr b/src/test/ui/const-generics/type-dependent/issue-71382.stderr
new file mode 100644 (file)
index 0000000..ad522ae
--- /dev/null
@@ -0,0 +1,8 @@
+error: using function pointers as const generic parameters is forbidden
+  --> $DIR/issue-71382.rs:12:23
+   |
+LL |     fn test<const FN: fn() -> u8>(&self) -> u8 {
+   |                       ^^^^^^^^^^
+
+error: aborting due to previous error
+
index 3701e14eadcfc1ecb3d824c09a646036c3702088..060b899648e65aabc90bd192a93f45e7783c71a7 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 use std::mem::MaybeUninit;
 
 trait CollectSlice<'a>: Iterator {
index 5d7dcb9c458ab3398eef1d82dfdd09cebc3a0ae8..5e1b8c635372326abe43cc5c2ba81bdc1f885ff3 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait Foo<'a, A>: Iterator<Item=A> {
     fn bar<const N: usize>(&mut self) -> *const [A; N];
 }
index 9e4afba311403fab2e6810ef9b26f1ad9267aa5f..b755de30b9ce9fafdbe910c47245c7061b873f48 100644 (file)
@@ -1,9 +1,5 @@
 // aux-build:type_dependent_lib.rs
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 extern crate type_dependent_lib;
 
 use type_dependent_lib::*;
index b61e970cfb37076ffc6c848ea127c518b8a29694..2d678d0acd3f7b79451318010ef0e3be6866fc39 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct A;
 impl A {
     fn foo<const N: usize>() -> usize { N + 1 }
index a4776a43b21160d892cbe0c00468f092eb88b344..1b13133b5b970715f21cd233d70c0dba16a3c7c4 100644 (file)
@@ -1,8 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct R;
 
 impl R {
index a0a14558490dafc58ae12d2b606a0c9b0c735209..02108d8596037315d86359153b0f1ea16b19c978 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch.rs:11:27
+  --> $DIR/type-mismatch.rs:8:27
    |
 LL |     assert_eq!(R.method::<1u16>(), 1);
    |                           ^^^^ expected `u8`, found `u16`
index a0a14558490dafc58ae12d2b606a0c9b0c735209..02108d8596037315d86359153b0f1ea16b19c978 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/type-mismatch.rs:11:27
+  --> $DIR/type-mismatch.rs:8:27
    |
 LL |     assert_eq!(R.method::<1u16>(), 1);
    |                           ^^^^ expected `u8`, found `u16`
index 7fba1afe9189f06b1a3b0fba782719ea70671777..3335ab870f49f9c1120f7b784aa2158bbb03dd89 100644 (file)
@@ -1,7 +1,4 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 struct R;
 
 impl R {
index f5053e4c8c8d3f348d55d25bca1812f8ac6b759e..8d779bee265cf2914c24c6f12b3272bb35578e5c 100644 (file)
@@ -4,12 +4,6 @@ error[E0308]: mismatched types
 LL |     bar::<N>()
    |           ^ expected `u8`, found `usize`
 
-error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:5:31
-   |
-LL | fn bar<const N: u8>() -> [u8; N] {}
-   |                               ^ expected `usize`, found `u8`
-
 error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:5:26
    |
@@ -18,6 +12,12 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
+error[E0308]: mismatched types
+  --> $DIR/type_mismatch.rs:5:31
+   |
+LL | fn bar<const N: u8>() -> [u8; N] {}
+   |                               ^ expected `usize`, found `u8`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 9a2e9f09319d8a15667e3c025081944b9eb65c83..fb0d688a8abf5d73f118857b6d05158f31613d6a 100644 (file)
@@ -1,9 +1,4 @@
 // run-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait T<const A: usize> {
     fn l<const N: bool>() -> usize;
     fn r<const N: bool>() -> bool;
index 480ecdb387346e06e044f399eb401fd70f30ebb6..565c9ba1ff1f67eb1658d0d5bf7230237dfda587 100644 (file)
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/types-mismatch-const-args.rs:14:41
    |
-LL |     let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32`
+LL |     let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32`
    |
    = note: expected type `2_u32`
               found type `4_u32`
index c19c8db737a191be7d8822c9a808e923dc2df31a..ec9221d2486ae6dee0e3c4d9fb74d18f69eb1272 100644 (file)
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
   --> $DIR/types-mismatch-const-args.rs:14:41
    |
-LL |     let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
-   |            --------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32`
+LL |     let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData };
+   |            --------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2_u32`, found `4_u32`
    |            |
    |            expected due to this
    |
index 14cef083d8373e393e7a9e4fcd7615b8b987a4cf..c2092c4268e803a234a4a9bdcce9333b4ae99ae9 100644 (file)
@@ -1,5 +1,5 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 // tests the diagnostic output of type mismatches for types that have const generics arguments.
@@ -11,7 +11,7 @@ struct A<'a, T, const X: u32, const Y: u32> {
 }
 
 fn a<'a, 'b>() {
-    let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData };
+    let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {2u32 + 2u32}, {3u32}> { data: PhantomData };
     //~^ ERROR mismatched types
     let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData };
     //~^ ERROR mismatched types
index 9592f26623070ab8390458a022a0244e4786ecf4..c7270e835c5a8391c27260451d9687c8c2f4f03c 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 use std::fmt;
 
index 4bab2bb5a77f57cf0bc34fc64634d944448874d8..191caa78f9e373f4b3cfc8f06ddcb7ad6745782c 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 use std::fmt;
 
diff --git a/src/test/ui/const-generics/unknown_adt.full.stderr b/src/test/ui/const-generics/unknown_adt.full.stderr
deleted file mode 100644 (file)
index b8b2e90..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0412]: cannot find type `UnknownStruct` in this scope
-  --> $DIR/unknown_adt.rs:7:12
-   |
-LL |     let _: UnknownStruct<7>;
-   |            ^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/const-generics/unknown_adt.min.stderr b/src/test/ui/const-generics/unknown_adt.min.stderr
deleted file mode 100644 (file)
index b8b2e90..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0412]: cannot find type `UnknownStruct` in this scope
-  --> $DIR/unknown_adt.rs:7:12
-   |
-LL |     let _: UnknownStruct<7>;
-   |            ^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0412`.
index 977f90aad116d1a12c28047198a846d2578398ce..8cdd28a8c60928033323e4625425c1e485ab97b0 100644 (file)
@@ -1,8 +1,3 @@
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 fn main() {
     let _: UnknownStruct<7>;
     //~^ ERROR cannot find type `UnknownStruct`
diff --git a/src/test/ui/const-generics/unknown_adt.stderr b/src/test/ui/const-generics/unknown_adt.stderr
new file mode 100644 (file)
index 0000000..0f462dd
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `UnknownStruct` in this scope
+  --> $DIR/unknown_adt.rs:2:12
+   |
+LL |     let _: UnknownStruct<7>;
+   |            ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
index 2918e399dc8ee7e8f7fc37416118457d84b1c0eb..c7f74cfac7d64446cf4e3ab67d19c506937cf81f 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 
 struct A<const N: usize>; // ok
 
index 836f26efc9601e7df2c5e00dc6e4c8c1e029c9e5..d080c210e6bd291c7c53467d263d631f0993861d 100644 (file)
@@ -1,11 +1,7 @@
 // check-pass
 // run-rustfix
-
-#![allow(incomplete_features)]
 #![warn(unused_braces)]
 
-#![feature(const_generics)]
-
 struct A<const N: usize>;
 
 fn main() {
diff --git a/src/test/ui/const-generics/unused_braces.full.stderr b/src/test/ui/const-generics/unused_braces.full.stderr
deleted file mode 100644 (file)
index 8899139..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: unnecessary braces around const expression
-  --> $DIR/unused_braces.rs:14:14
-   |
-LL |     let _: A<{ 7 }>;
-   |              ^^^^^ help: remove these braces
-   |
-note: the lint level is defined here
-  --> $DIR/unused_braces.rs:7:9
-   |
-LL | #![warn(unused_braces)]
-   |         ^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const-generics/unused_braces.min.stderr b/src/test/ui/const-generics/unused_braces.min.stderr
deleted file mode 100644 (file)
index 8899139..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: unnecessary braces around const expression
-  --> $DIR/unused_braces.rs:14:14
-   |
-LL |     let _: A<{ 7 }>;
-   |              ^^^^^ help: remove these braces
-   |
-note: the lint level is defined here
-  --> $DIR/unused_braces.rs:7:9
-   |
-LL | #![warn(unused_braces)]
-   |         ^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
index 0348bbacaabd2496f024a3d64604a450a394e1c9..47f0f8c1c96c91ba2d08368fc460b3401703b611 100644 (file)
@@ -1,12 +1,7 @@
 // check-pass
 // run-rustfix
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
 #![warn(unused_braces)]
 
-
 struct A<const N: usize>;
 
 fn main() {
diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr
new file mode 100644 (file)
index 0000000..5e1bace
--- /dev/null
@@ -0,0 +1,14 @@
+warning: unnecessary braces around const expression
+  --> $DIR/unused_braces.rs:9:14
+   |
+LL |     let _: A<{ 7 }>;
+   |              ^^^^^ help: remove these braces
+   |
+note: the lint level is defined here
+  --> $DIR/unused_braces.rs:3:9
+   |
+LL | #![warn(unused_braces)]
+   |         ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/const-generics/wf-misc.full.stderr b/src/test/ui/const-generics/wf-misc.full.stderr
deleted file mode 100644 (file)
index dfb593a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error: constant expression depends on a generic parameter
-  --> $DIR/wf-misc.rs:8:12
-   |
-LL |     let _: [u8; N + 1];
-   |            ^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
-  --> $DIR/wf-misc.rs:16:12
-   |
-LL |     let _: Const::<{N + 1}>;
-   |            ^^^^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/wf-misc.min.stderr b/src/test/ui/const-generics/wf-misc.min.stderr
deleted file mode 100644 (file)
index 9967a22..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/wf-misc.rs:8:17
-   |
-LL |     let _: [u8; N + 1];
-   |                 ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: generic parameters may not be used in const operations
-  --> $DIR/wf-misc.rs:16:21
-   |
-LL |     let _: Const::<{N + 1}>;
-   |                     ^ cannot perform const operation using `N`
-   |
-   = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/const-generics/wf-misc.rs b/src/test/ui/const-generics/wf-misc.rs
deleted file mode 100644 (file)
index 8a5b6dd..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Tests miscellaneous well-formedness examples.
-// revisions: full min
-
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
-pub fn arr_len<const N: usize>() {
-    let _: [u8; N + 1];
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
-}
-
-struct Const<const N: usize>;
-
-pub fn func_call<const N: usize>() {
-    let _: Const::<{N + 1}>;
-    //[full]~^ ERROR constant expression depends on a generic parameter
-    //[min]~^^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
index dc09cad3180bfbf6f8d3603c1f52b2596870818a..aa3ca1cf6de73d4e48af20edcfad5eca289e42db 100644 (file)
@@ -1,8 +1,4 @@
 // check-pass
-// revisions: full min
-#![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
-
 trait Bar<const N: usize> { fn bar() {} }
 trait Foo<const N: usize>: Bar<N> {}
 
diff --git a/src/test/ui/const_evaluatable/associated-const.rs b/src/test/ui/const_evaluatable/associated-const.rs
deleted file mode 100644 (file)
index a677763..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// check-pass
-struct Foo<T>(T);
-impl<T> Foo<T> {
-    const VALUE: usize = std::mem::size_of::<T>();
-}
-
-fn test<T>() {
-    let _ = [0; Foo::<u8>::VALUE];
-}
-
-fn main() {}
diff --git a/src/test/ui/const_evaluatable/function-call.rs b/src/test/ui/const_evaluatable/function-call.rs
deleted file mode 100644 (file)
index b5de666..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// check-pass
-
-const fn foo<T>() -> usize {
-    // We might instead branch on `std::mem::size_of::<*mut T>() < 8` here,
-    // which would cause this function to fail on 32 bit systems.
-    if false {
-        std::mem::size_of::<T>()
-    } else {
-        8
-    }
-}
-
-fn test<T>() {
-    let _ = [0; foo::<T>()];
-    //~^ WARN cannot use constants which depend on generic parameters in types
-    //~| WARN this was previously accepted by the compiler but is being phased out
-}
-
-fn main() {}
diff --git a/src/test/ui/const_evaluatable/function-call.stderr b/src/test/ui/const_evaluatable/function-call.stderr
deleted file mode 100644 (file)
index 0d84637..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/function-call.rs:14:17
-   |
-LL |     let _ = [0; foo::<T>()];
-   |                 ^^^^^^^^^^
-   |
-   = note: `#[warn(const_evaluatable_unchecked)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/const_evaluatable/needs_where_clause.rs b/src/test/ui/const_evaluatable/needs_where_clause.rs
deleted file mode 100644 (file)
index 498a2ae..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#![crate_type = "lib"]
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features)]
-
-const fn complex_maths<T>(n : usize) -> usize {
-  2 * n + 1
-}
-
-struct Example<T, const N: usize> {
-  a: [f32; N],
-  b: [f32; complex_maths::<T>(N)],
-  //~^ ERROR unconstrained
-  c: T,
-}
diff --git a/src/test/ui/const_evaluatable/needs_where_clause.stderr b/src/test/ui/const_evaluatable/needs_where_clause.stderr
deleted file mode 100644 (file)
index 7b41e39..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/needs_where_clause.rs:11:6
-   |
-LL |   b: [f32; complex_maths::<T>(N)],
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); complex_maths::<T>(N)]:`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const_evaluatable/no_where_clause.rs b/src/test/ui/const_evaluatable/no_where_clause.rs
deleted file mode 100644 (file)
index 12f4a22..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#![feature(const_generics, const_evaluatable_checked)]
-#![allow(incomplete_features, unused)]
-
-const fn complex_maths(n : usize) -> usize {
-  2 * n + 1
-}
-
-pub struct Example<const N: usize> {
-  a: [f32; N],
-  b: [f32; complex_maths(N)],
-  //~^ ERROR unconstrained generic
-}
-
-impl<const N: usize> Example<N> {
-  pub fn new() -> Self {
-    Self {
-      a: [0.; N],
-      b: [0.; complex_maths(N)],
-    }
-  }
-}
-
-impl Example<2> {
-  pub fn sum(&self) -> f32 {
-    self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>()
-  }
-}
-
-fn main() {}
diff --git a/src/test/ui/const_evaluatable/no_where_clause.stderr b/src/test/ui/const_evaluatable/no_where_clause.stderr
deleted file mode 100644 (file)
index 3e5c2f5..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained generic constant
-  --> $DIR/no_where_clause.rs:10:6
-   |
-LL |   b: [f32; complex_maths(N)],
-   |      ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); complex_maths(N)]:`
-
-error: aborting due to previous error
-
index d01376e595945f8cb0fbb65254dff3687cd12e8b..3b5a0f22f28bef1de3913372e13cbb857b825c83 100644 (file)
@@ -1,8 +1,8 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/infinite_loop.rs:7:17
+  --> $DIR/infinite_loop.rs:7:20
    |
 LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   |                    ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
 
 error: aborting due to previous error
 
index bb8113e53f9c19f917d1e5fd4cd694860d02a899..80f6bbec2a181f04d6146376b12e96c246ee72a8 100644 (file)
@@ -1,22 +1,13 @@
 // issue-49296: Unsafe shenigans in constants can result in missing errors
 
 #![feature(const_fn_trait_bound)]
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
 
-const unsafe fn transmute<T: ?const Copy, U: ?const Copy>(t: T) -> U {
-    #[repr(C)]
-    union Transmute<T: Copy, U: Copy> {
-        from: T,
-        to: U,
-    }
-
-    Transmute { from: t }.to
-}
+use std::mem::transmute;
 
 const fn wat(x: u64) -> &'static u64 {
     unsafe { transmute(&x) }
 }
+
 const X: u64 = *wat(42);
 //~^ ERROR evaluation of constant value failed
 
index 28fdcb7c486371ddb1cdfaf37b0dd789b54733be..bc3074b10bee6f326c048121d07b093515e63e46 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-49296.rs:20:16
+  --> $DIR/issue-49296.rs:11:16
    |
 LL | const X: u64 = *wat(42);
    |                ^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
index b643ecc0ce8d98047bc458e7aeff00114368c70e..33014a1500cf7061793586bf57f37ac5db885ea3 100644 (file)
@@ -1,16 +1,16 @@
 error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
-  --> $DIR/const-extern-fn-requires-unsafe.rs:11:5
+  --> $DIR/const-extern-fn-requires-unsafe.rs:9:17
    |
-LL |     foo();
-   |     ^^^^^ call to unsafe function
+LL |     let a: [u8; foo()];
+   |                 ^^^^^ call to unsafe function
    |
    = 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/const-extern-fn-requires-unsafe.rs:9:17
+  --> $DIR/const-extern-fn-requires-unsafe.rs:11:5
    |
-LL |     let a: [u8; foo()];
-   |                 ^^^^^ call to unsafe function
+LL |     foo();
+   |     ^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
index 9f66e3cfa23c0d271b29ff98ce067441f41a3c6b..7402c680985b0059aee031a9b8bcdff4c14d973f 100644 (file)
@@ -1,5 +1,5 @@
 // Check that evaluation of needs_drop<T> fails when T is not monomorphic.
-#![feature(const_generics)]
+#![feature(generic_const_exprs)]
 #![allow(const_evaluatable_unchecked)]
 #![allow(incomplete_features)]
 
@@ -10,7 +10,7 @@ fn assert() {}
 fn f<T>() {
     Bool::<{ std::mem::needs_drop::<T>() }>::assert();
     //~^ ERROR no function or associated item named `assert` found
-    //~| ERROR constant expression depends on a generic parameter
+    //~| ERROR unconstrained generic constant
 }
 fn main() {
     f::<u32>();
index 0770d06e15be8c2ca516c3c3715975321207598d..6e56d20c39d7f709463c0184b8a1b5502af073f8 100644 (file)
@@ -7,13 +7,13 @@ LL | struct Bool<const B: bool> {}
 LL |     Bool::<{ std::mem::needs_drop::<T>() }>::assert();
    |                                              ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::<T>() }>` due to unsatisfied trait bounds
 
-error: constant expression depends on a generic parameter
+error: unconstrained generic constant
   --> $DIR/const-needs_drop-monomorphic.rs:11:5
    |
 LL |     Bool::<{ std::mem::needs_drop::<T>() }>::assert();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: this may fail depending on what value the parameter takes
+   = help: try adding a `where` bound using this expression: `where [(); { std::mem::needs_drop::<T>() }]:`
 
 error: aborting due to 2 previous errors
 
index 129457ebdf92913bd58756b2c687a2bfd344661c..1067eb003f7c765ad92b045730a3f2254fba575f 100644 (file)
@@ -15,6 +15,7 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
    = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
index 10e54e0348cb7d45ecaf6866ffed2c4710cf8ea0..5e706a4466ea176cf2ba6a4e4f16362f1df5aef9 100644 (file)
@@ -1,19 +1,15 @@
 error: any use of this value will cause an error
-  --> $DIR/const_eval_limit_reached.rs:6:5
+  --> $DIR/const_eval_limit_reached.rs:6:11
    |
-LL |  / const X: usize = {
-LL |  |     let mut x = 0;
-LL |  |     while x != 1000 {
-   |  |_____^
-LL | ||
-LL | ||
-LL | ||         x += 1;
-LL | ||     }
-   | ||_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-LL |  |
-LL |  |     x
-LL |  | };
-   |  |__-
+LL | / const X: usize = {
+LL | |     let mut x = 0;
+LL | |     while x != 1000 {
+   | |           ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | |
+...  |
+LL | |     x
+LL | | };
+   | |__-
    |
    = note: `#[deny(const_err)]` on by default
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
index 38841e99a72206f85fc2b18aa32d12e4554d87b8..9e3db5ce9a402ce3cdce028910d1d27821be98c5 100644 (file)
@@ -15,6 +15,7 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`..
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    |                 ^^^^^^
    = note: ...which requires computing layout of `Foo`...
+   = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
    = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
index 50c95c89e0b79485f1e770c344ca98b7fddcb20d..3349e9813a809e08a19bdc9e5ec2ca27c49d80db 100644 (file)
@@ -1,11 +1,3 @@
-error: argument to `panic!()` in a const context must have type `&str`
-  --> $DIR/issue-66693.rs:13:5
-   |
-LL |     panic!(&1);
-   |     ^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error: argument to `panic!()` in a const context must have type `&str`
   --> $DIR/issue-66693.rs:6:15
    |
@@ -22,5 +14,13 @@ LL | static _FOO: () = panic!(true);
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: argument to `panic!()` in a const context must have type `&str`
+  --> $DIR/issue-66693.rs:13:5
+   |
+LL |     panic!(&1);
+   |     ^^^^^^^^^^^
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: aborting due to 3 previous errors
 
index 64a1214e8bf1b06995039b00c38f9c827c3923b9..64d8540878ec227263adb6fe5116ddcedeb8a5c2 100644 (file)
@@ -65,11 +65,11 @@ LL |         U8_MUT2 => true,
    |         ^^^^^^^
 
 warning: any use of this value will cause an error
-  --> $DIR/const_refers_to_static_cross_crate.rs:32:51
+  --> $DIR/const_refers_to_static_cross_crate.rs:32:20
    |
 LL | / const U8_MUT3: &u8 = {
 LL | |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   | |                                                   ^^^^^^^^^^^ constant accesses static
+   | |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 LL | |
 LL | |
 LL | |
index 66fe4ec076005eabab019bc48fba0edea4700ffc..8e793ab3f0d916394d6d67a96417745433e965f2 100644 (file)
@@ -65,11 +65,11 @@ LL |         U8_MUT2 => true,
    |         ^^^^^^^
 
 warning: any use of this value will cause an error
-  --> $DIR/const_refers_to_static_cross_crate.rs:32:51
+  --> $DIR/const_refers_to_static_cross_crate.rs:32:20
    |
 LL | / const U8_MUT3: &u8 = {
 LL | |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   | |                                                   ^^^^^^^^^^^ constant accesses static
+   | |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 LL | |
 LL | |
 LL | |
index 58c458709a839513e898af68432ef03631f915a8..fc842fada5a0d9892ef026ce080385844e3627de 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing type of `Foo::X`
 LL | trait Foo<X = Box<dyn Foo>> {
    |                       ^^^
    |
-   = note: ...which again requires computing type of `Foo::X`, completing the cycle
+   = note: ...which immediately requires computing type of `Foo::X` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-default-type-trait.rs:4:1
    |
@@ -17,7 +17,7 @@ error[E0391]: cycle detected when computing type of `Foo::X`
 LL | trait Foo<X = Box<dyn Foo>> {
    |                       ^^^
    |
-   = note: ...which again requires computing type of `Foo::X`, completing the cycle
+   = note: ...which immediately requires computing type of `Foo::X` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/cycle-trait-default-type-trait.rs:4:1
    |
index 0e92cc5c9f282a70153f0c9495ba5b48cf8a3522..9aae4b0a3faed76175690c36c9f153cb626a6b6e 100644 (file)
@@ -15,22 +15,22 @@ LL |     Enum::SingleVariant(a, .., b, ..) = Enum::SingleVariant(0, 1);
    |                            previously used here
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple struct has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:30:5
+  --> $DIR/tuple_struct_destructure_fail.rs:30:17
    |
 LL | struct TupleStruct<S, T>(S, T);
-   | ------------------------------- tuple struct defined here
+   |                          -  - tuple struct has 2 fields
 ...
 LL |     TupleStruct(a, a, b) = TupleStruct(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                 ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:32:5
+  --> $DIR/tuple_struct_destructure_fail.rs:32:17
    |
 LL | struct TupleStruct<S, T>(S, T);
-   | ------------------------------- tuple struct defined here
+   |                          -  - tuple struct has 2 fields
 ...
 LL |     TupleStruct(_) = TupleStruct(1, 2);
-   |     ^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                 ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -42,22 +42,22 @@ LL |     TupleStruct(..) = TupleStruct(1, 2);
    |                 ~~
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:34:5
+  --> $DIR/tuple_struct_destructure_fail.rs:34:25
    |
 LL |     SingleVariant(S, T)
-   |     ------------------- tuple variant defined here
+   |                   -  - tuple variant has 2 fields
 ...
 LL |     Enum::SingleVariant(a, a, b) = Enum::SingleVariant(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                         ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/tuple_struct_destructure_fail.rs:36:5
+  --> $DIR/tuple_struct_destructure_fail.rs:36:25
    |
 LL |     SingleVariant(S, T)
-   |     ------------------- tuple variant defined here
+   |                   -  - tuple variant has 2 fields
 ...
 LL |     Enum::SingleVariant(_) = Enum::SingleVariant(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                         ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
index 838e81043db7bbfb72a46339f99c442b21839862..88617381236d7377fe5717f613c14c52193f9a27 100644 (file)
@@ -1,11 +1,19 @@
 error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-31424.rs:7:9
    |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/issue-31424.rs:6:12
+   |
+LL |     fn foo(&mut self) {
+   |            ^^^^^^^^^
+help: try removing `&mut` here
+  --> $DIR/issue-31424.rs:7:9
+   |
 LL |         (&mut self).bar();
    |         ^^^^^^^^^^^
-   |         |
-   |         cannot borrow as mutable
-   |         help: try removing `&mut` here
 
 warning: function cannot return without recursing
   --> $DIR/issue-31424.rs:13:5
@@ -22,11 +30,19 @@ LL |         (&mut self).bar();
 error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-31424.rs:16:9
    |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/issue-31424.rs:13:18
+   |
+LL |     fn bar(self: &mut Self) {
+   |                  ^^^^^^^^^
+help: try removing `&mut` here
+  --> $DIR/issue-31424.rs:16:9
+   |
 LL |         (&mut self).bar();
    |         ^^^^^^^^^^^
-   |         |
-   |         cannot borrow as mutable
-   |         help: try removing `&mut` here
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
index 669684fb3ddd743f2c4859b91cd8bb779c7f259b..666172197ce9b01be64be88936a201bec1997282 100644 (file)
@@ -2,10 +2,18 @@ error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-34126.rs:6:18
    |
 LL |         self.run(&mut self);
-   |                  ^^^^^^^^^
-   |                  |
-   |                  cannot borrow as mutable
-   |                  help: try removing `&mut` here
+   |                  ^^^^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/issue-34126.rs:5:14
+   |
+LL |     fn start(&mut self) {
+   |              ^^^^^^^^^
+help: try removing `&mut` here
+   |
+LL -         self.run(&mut self);
+LL +         self.run(self);
+   | 
 
 error[E0502]: cannot borrow `self` as mutable because it is also borrowed as immutable
   --> $DIR/issue-34126.rs:6:18
index f4bc5aef82dc3c5c91e0f1f37c4891728a260ecf..d2938435ece31b0ae435d0b714ddfaa9ee51193d 100644 (file)
@@ -31,11 +31,11 @@ help: use `::<...>` instead of `<...>` to specify type or const arguments
 LL |     (0..13).collect::<Vec<i32>();
    |                    ++
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-40396.rs:11:43
    |
 LL |     let x = std::collections::HashMap<i128, i128>::new();
-   |                                           ^ expected one of 7 possible tokens
+   |                                           ^ expected one of 8 possible tokens
    |
 help: use `::<...>` instead of `<...>` to specify type or const arguments
    |
diff --git a/src/test/ui/drop/drop-if-let-binding.rs b/src/test/ui/drop/drop-if-let-binding.rs
new file mode 100644 (file)
index 0000000..9c1ac4e
--- /dev/null
@@ -0,0 +1,7 @@
+// build-pass
+// regression test for issue #88307
+// compile-flags: -C opt-level=s
+
+fn main() {
+    if let Some(_val) = Option::<String>::None {}
+}
index fb13fd764bfaf8369b236abf1d3bbbe6387977f2..27a599315dc1c580095682525d05da3f03237c4e 100644 (file)
@@ -368,7 +368,7 @@ pub fn main() {
     // We can use refcells if we're single-threaded (as this test is).
     // If one were to generalize these constructions to a
     // multi-threaded context, then it might seem like we could choose
-    // between either a RwLock or a Mutex to hold the owned arcs on
+    // between either an RwLock or a Mutex to hold the owned arcs on
     // each node.
     //
     // Part of the point of this test is to actually confirm that the
diff --git a/src/test/ui/dyn-keyword/dyn-angle-brackets.fixed b/src/test/ui/dyn-keyword/dyn-angle-brackets.fixed
new file mode 100644 (file)
index 0000000..25caa6a
--- /dev/null
@@ -0,0 +1,23 @@
+// See https://github.com/rust-lang/rust/issues/88508
+// run-rustfix
+// edition:2018
+#![deny(bare_trait_objects)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+use std::fmt;
+
+#[derive(Debug)]
+pub struct Foo;
+
+impl fmt::Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        <dyn fmt::Debug>::fmt(self, f)
+        //~^ ERROR trait objects without an explicit `dyn` are deprecated
+        //~| WARNING this is accepted in the current edition
+        //~| ERROR trait objects without an explicit `dyn` are deprecated
+        //~| WARNING this is accepted in the current edition
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/dyn-keyword/dyn-angle-brackets.rs b/src/test/ui/dyn-keyword/dyn-angle-brackets.rs
new file mode 100644 (file)
index 0000000..cf72da2
--- /dev/null
@@ -0,0 +1,23 @@
+// See https://github.com/rust-lang/rust/issues/88508
+// run-rustfix
+// edition:2018
+#![deny(bare_trait_objects)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+use std::fmt;
+
+#[derive(Debug)]
+pub struct Foo;
+
+impl fmt::Display for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        <fmt::Debug>::fmt(self, f)
+        //~^ ERROR trait objects without an explicit `dyn` are deprecated
+        //~| WARNING this is accepted in the current edition
+        //~| ERROR trait objects without an explicit `dyn` are deprecated
+        //~| WARNING this is accepted in the current edition
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr b/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr
new file mode 100644 (file)
index 0000000..ef0f5b7
--- /dev/null
@@ -0,0 +1,25 @@
+error: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/dyn-angle-brackets.rs:15:10
+   |
+LL |         <fmt::Debug>::fmt(self, f)
+   |          ^^^^^^^^^^ help: use `dyn`: `dyn fmt::Debug`
+   |
+note: the lint level is defined here
+  --> $DIR/dyn-angle-brackets.rs:4:9
+   |
+LL | #![deny(bare_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+
+error: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/dyn-angle-brackets.rs:15:10
+   |
+LL |         <fmt::Debug>::fmt(self, f)
+   |          ^^^^^^^^^^ help: use `dyn`: `dyn fmt::Debug`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+
+error: aborting due to 2 previous errors
+
index 92eae9e3c14f8ca4df0e01a23a461fff82cd65bf..24112c9855acd1d967f95ce213a708839086f553 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 = "2018"` in `Cargo.toml`
+//~| HELP set `edition = "2021"` in `Cargo.toml`
 //~| 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 = "2018"` in `Cargo.toml`
+        //~| HELP set `edition = "2021"` in `Cargo.toml`
         //~| 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 = "2018"` in `Cargo.toml`
+        //~| HELP set `edition = "2021"` in `Cargo.toml`
         //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide
     };
     y.await;
index e42747c804c714c0ceb98052838b4562d53926f2..da8412ddcb3333eafba7940ad8b8bca6526d80a2 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = 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
diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.rs b/src/test/ui/editions/dyn-trait-sugg-2021.rs
new file mode 100644 (file)
index 0000000..47c48e7
--- /dev/null
@@ -0,0 +1,12 @@
+// edition:2021
+
+trait Foo<T> {}
+
+impl<T> dyn Foo<T> {
+    fn hi(_x: T)  {}
+}
+
+fn main() {
+    Foo::hi(123);
+    //~^ ERROR trait objects without an explicit `dyn` are deprecated
+}
diff --git a/src/test/ui/editions/dyn-trait-sugg-2021.stderr b/src/test/ui/editions/dyn-trait-sugg-2021.stderr
new file mode 100644 (file)
index 0000000..f6e9fa9
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0783]: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/dyn-trait-sugg-2021.rs:10:5
+   |
+LL |     Foo::hi(123);
+   |     ^^^ help: use `dyn`: `<dyn Foo>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0783`.
index 4d57765e13f5adcc3f4cebbf631a8ffe85a45733..e4e10468d53488e052c24f6f6141186b7d137cb3 100644 (file)
@@ -5,7 +5,7 @@ LL |     Some(T) = std::mem::size_of::<T>(),
    |                                   ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index f89be630eeb30c7746fbedbecfb2a6f28e8a8407..7ea8a39129ead9e859f0bca4a25dae3d2b07d9b1 100644 (file)
@@ -5,7 +5,7 @@ LL |     Some = std::mem::size_of::<T>(),
    |                                ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0392]: parameter `T` is never used
   --> $DIR/issue-70453-generics-in-discr-ice.rs:7:20
index 8c97af263b287f98e4bac301370513fcd0a643cd..0a7a631606ee4e14116d8e6d1c172a9e397a84fc 100644 (file)
@@ -5,7 +5,7 @@ LL |     Some(T) = core::mem::size_of::<*mut T>(),
    |                                         ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 227899e75350f3ed155d2640315c2b61b02764df..8f1b5b38e4c351db1a6fbe533e43673c78fe620d 100644 (file)
@@ -5,7 +5,7 @@ LL |         let x: S = 0;
    |                ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0392]: parameter `S` is never used
   --> $DIR/issue-67945-1.rs:1:10
index 5a90f00c346d0de0f44b8d131f96592318e836a1..4f5e236a37b45ec92dff46f15b621f067ae0b2ff 100644 (file)
@@ -5,7 +5,7 @@ LL |     Var = 0: S,
    |              ^ cannot perform const operation using `S`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error[E0392]: parameter `S` is never used
   --> $DIR/issue-67945-2.rs:3:10
index ec3aae29714103601cc778f2f0d0c608dec1f535..3e321b037b2b2d5ba59f171e8c1a594c91ee1f90 100644 (file)
@@ -1,11 +1,11 @@
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/E0023.rs:11:9
+  --> $DIR/E0023.rs:11:22
    |
 LL |     Apple(String, String),
-   |     --------------------- tuple variant defined here
+   |           ------  ------ tuple variant has 2 fields
 ...
 LL |         Fruit::Apple(a) => {},
-   |         ^^^^^^^^^^^^^^^ expected 2 fields, found 1
+   |                      ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -13,31 +13,31 @@ LL |         Fruit::Apple(a, _) => {},
    |                       +++
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/E0023.rs:12:9
+  --> $DIR/E0023.rs:12:22
    |
 LL |     Apple(String, String),
-   |     --------------------- tuple variant defined here
+   |           ------  ------ tuple variant has 2 fields
 ...
 LL |         Fruit::Apple(a, b, c) => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^ expected 2 fields, found 3
+   |                      ^  ^  ^ expected 2 fields, found 3
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
-  --> $DIR/E0023.rs:13:9
+  --> $DIR/E0023.rs:13:21
    |
 LL |     Pear(u32),
-   |     --------- tuple variant defined here
+   |          --- tuple variant has 1 field
 ...
 LL |         Fruit::Pear(1, 2) => {},
-   |         ^^^^^^^^^^^^^^^^^ expected 1 field, found 2
+   |                     ^  ^ expected 1 field, found 2
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 1 field
-  --> $DIR/E0023.rs:14:9
+  --> $DIR/E0023.rs:14:23
    |
 LL |     Orange((String, String)),
-   |     ------------------------ tuple variant defined here
+   |            ---------------- tuple variant has 1 field
 ...
 LL |         Fruit::Orange(a, b) => {},
-   |         ^^^^^^^^^^^^^^^^^^^ expected 1 field, found 2
+   |                       ^  ^ expected 1 field, found 2
    |
 help: missing parentheses
    |
@@ -48,7 +48,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has
   --> $DIR/E0023.rs:15:9
    |
 LL |     Banana(()),
-   |     ---------- tuple variant defined here
+   |            -- tuple variant has 1 field
 ...
 LL |         Fruit::Banana() => {},
    |         ^^^^^^^^^^^^^^^ expected 1 field, found 0
index d716ca1a14fdf3cbfafb57a116ab03198fa576b9..ee8e5e6dffee3c619d69f3deb9d119a10ba16c36 100644 (file)
@@ -2,7 +2,7 @@
 #![feature(lang_items)]
 
 #[lang = "owned_box"]
-struct Foo; //~ ERROR E0152
+struct Foo<T>(T); //~ ERROR E0152
 
 fn main() {
 }
index 7445c2880af1c0a98e8b858439fa518a6cad7eb8..5cdfe1cc5562d408e166bd3aa8aa391564953f6f 100644 (file)
@@ -1,8 +1,8 @@
 error[E0152]: found duplicate lang item `owned_box`
   --> $DIR/E0152.rs:5:1
    |
-LL | struct Foo;
-   | ^^^^^^^^^^^
+LL | struct Foo<T>(T);
+   | ^^^^^^^^^^^^^^^^^
    |
    = note: the lang item is first defined in crate `alloc` (which `std` depends on)
    = note: first definition in `alloc` loaded from SYSROOT/liballoc-*.rlib
index 30745814b4a744456d74555c54c7ff511e02ee8d..04f5e5d4257458c20c405a46641b01ce10be560e 100644 (file)
@@ -1,6 +1,3 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
-
 fn is_123<const N: usize>(x: [u32; N]) -> bool {
     match x {
         [1, 2, ..] => true, //~ ERROR cannot pattern-match on an array without a fixed length
index f915f6edef52b974c652b106e903b77eeaad96d3..067e8c57cd63b172c868bda9a53b199618b87e28 100644 (file)
@@ -1,18 +1,9 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/E0730.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
 error[E0730]: cannot pattern-match on an array without a fixed length
-  --> $DIR/E0730.rs:6:9
+  --> $DIR/E0730.rs:3:9
    |
 LL |         [1, 2, ..] => true,
    |         ^^^^^^^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0730`.
index ba3592719408c5bc997e51a4076312a5f7766cd1..67e7d106a1fcee0feff74318c9a4cf09038231c0 100644 (file)
@@ -1,5 +1,5 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![feature(adt_const_params)]
+//~^ WARN the feature `adt_const_params` is incomplete
 
 fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0771
 
index 60220be6b57ba55e1667c790aa3dfd05b723c0f5..730a7ef1284b612a66266f889adc1f69531c3dc5 100644 (file)
@@ -1,8 +1,8 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/E0771.rs:1:12
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+LL | #![feature(adt_const_params)]
+   |            ^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
diff --git a/src/test/ui/extern/extern-no-mangle.rs b/src/test/ui/extern/extern-no-mangle.rs
new file mode 100644 (file)
index 0000000..ab7c982
--- /dev/null
@@ -0,0 +1,30 @@
+#![warn(unused_attributes)]
+
+// Tests that placing the #[no_mangle] attribute on a foreign fn or static emits
+// a specialized warning.
+// The previous warning only talks about a "function or static" but foreign fns/statics
+// are also not allowed to have #[no_mangle]
+
+// build-pass
+
+extern "C" {
+    #[no_mangle]
+    //~^ WARNING `#[no_mangle]` has no effect on a foreign static
+    //~^^ WARNING this was previously accepted by the compiler
+    pub static FOO: u8;
+
+    #[no_mangle]
+    //~^ WARNING `#[no_mangle]` has no effect on a foreign function
+    //~^^ WARNING this was previously accepted by the compiler
+    pub fn bar();
+}
+
+fn no_new_warn() {
+    // Should emit the generic "not a function or static" warning
+    #[no_mangle]
+    //~^ WARNING attribute should be applied to a free function, impl method or static
+    //~^^ WARNING this was previously accepted by the compiler
+    let x = 0_u8;
+}
+
+fn main() {}
diff --git a/src/test/ui/extern/extern-no-mangle.stderr b/src/test/ui/extern/extern-no-mangle.stderr
new file mode 100644 (file)
index 0000000..b564281
--- /dev/null
@@ -0,0 +1,42 @@
+warning: attribute should be applied to a free function, impl method or static
+  --> $DIR/extern-no-mangle.rs:24:5
+   |
+LL |     #[no_mangle]
+   |     ^^^^^^^^^^^^
+...
+LL |     let x = 0_u8;
+   |     ------------- not a free function, impl method or static
+   |
+note: the lint level is defined here
+  --> $DIR/extern-no-mangle.rs:1:9
+   |
+LL | #![warn(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+warning: `#[no_mangle]` has no effect on a foreign static
+  --> $DIR/extern-no-mangle.rs:11:5
+   |
+LL |     #[no_mangle]
+   |     ^^^^^^^^^^^^ help: remove this attribute
+...
+LL |     pub static FOO: u8;
+   |     ------------------- foreign static
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: symbol names in extern blocks are not mangled
+
+warning: `#[no_mangle]` has no effect on a foreign function
+  --> $DIR/extern-no-mangle.rs:16:5
+   |
+LL |     #[no_mangle]
+   |     ^^^^^^^^^^^^ help: remove this attribute
+...
+LL |     pub fn bar();
+   |     ------------- foreign function
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: symbol names in extern blocks are not mangled
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/feature-gates/feature-gate-adt_const_params.rs b/src/test/ui/feature-gates/feature-gate-adt_const_params.rs
new file mode 100644 (file)
index 0000000..8a3bcf2
--- /dev/null
@@ -0,0 +1,2 @@
+struct Foo<const NAME: &'static str>; //~ ERROR `&'static str` is forbidden
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-adt_const_params.stderr b/src/test/ui/feature-gates/feature-gate-adt_const_params.stderr
new file mode 100644 (file)
index 0000000..d8f089a
--- /dev/null
@@ -0,0 +1,11 @@
+error: `&'static str` is forbidden as the type of a const generic parameter
+  --> $DIR/feature-gate-adt_const_params.rs:1:24
+   |
+LL | struct Foo<const NAME: &'static str>;
+   |                        ^^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = help: more complex types are supported with `#![feature(adt_const_params)]`
+
+error: aborting due to previous error
+
index f24c3d69a265bd1e36f069dfc5c411b0e6382cbd..8df5fbcc7eba290e17c5d8c0f20ab15f3a6de60d 100644 (file)
@@ -142,8 +142,10 @@ LL |     type A: Iterator<Item: Copy>;
 note: required by a bound in `Copy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
    |
-LL | pub trait Copy: Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Copy`
+LL | / pub trait Copy: Clone {
+LL | |     // Empty.
+LL | | }
+   | |_^ required by this bound in `Copy`
 help: consider further restricting the associated type
    |
 LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy {
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.rs b/src/test/ui/feature-gates/feature-gate-const_generics.rs
deleted file mode 100644 (file)
index 06364ee..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn foo<const X: ()>() {} //~ ERROR `()` is forbidden as the type of a const generic parameter
-
-struct Foo<const X: usize>([(); X]);
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
deleted file mode 100644 (file)
index ed19109..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: `()` is forbidden as the type of a const generic parameter
-  --> $DIR/feature-gate-const_generics.rs:1:17
-   |
-LL | fn foo<const X: ()>() {}
-   |                 ^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#![feature(const_generics)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/feature-gates/feature-gate-let_else.rs b/src/test/ui/feature-gates/feature-gate-let_else.rs
new file mode 100644 (file)
index 0000000..3f04a9d
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    let Some(x) = Some(1) else { //~ ERROR `let...else` statements are unstable
+        return;
+    };
+}
diff --git a/src/test/ui/feature-gates/feature-gate-let_else.stderr b/src/test/ui/feature-gates/feature-gate-let_else.stderr
new file mode 100644 (file)
index 0000000..8625260
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0658]: `let...else` statements are unstable
+  --> $DIR/feature-gate-let_else.rs:2:5
+   |
+LL | /     let Some(x) = Some(1) else {
+LL | |         return;
+LL | |     };
+   | |______^
+   |
+   = note: see issue #87335 <https://github.com/rust-lang/rust/issues/87335> for more information
+   = help: add `#![feature(let_else)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
index 5c10a7c781183e3ad7600e1499b1bebd8bbe016a..4e89fc975d04c95a1dde7a892cedcfd3f146e0c0 100644 (file)
@@ -11,7 +11,6 @@
 // of the underlying generator.
 
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 async fn f() -> u8 { 1 }
 async fn foo() -> [bool; 10] { [false; 10] }
diff --git a/src/test/ui/generic-associated-types/issue-87429-2.rs b/src/test/ui/generic-associated-types/issue-87429-2.rs
new file mode 100644 (file)
index 0000000..d35bb09
--- /dev/null
@@ -0,0 +1,20 @@
+// Derived from `issue-87429`. A test that ensures that using bound vars in the
+// predicates in the param env when checking that an associated type satisfies
+// its bounds does not cause us to not be able to use the bounds on the parameters.
+
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a, C: Eq>: for<'b> MyBound<'b, C>;
+}
+
+trait MyBound<'a, C> { }
+impl<'a, C: Eq> MyBound<'a, C> for i32 { }
+
+impl Family for () {
+    type Member<'a, C: Eq> = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.rs
new file mode 100644 (file)
index 0000000..9ee07c2
--- /dev/null
@@ -0,0 +1,18 @@
+// check-fail
+
+#![feature(associated_type_defaults)]
+#![feature(generic_associated_types)]
+
+trait Family {
+    // Fine, i32: PartialEq<i32>
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = i32;
+}
+
+struct Foo;
+trait Family2 {
+    // Not fine, not Foo: PartialEq<Foo>
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+    //~^ ERROR can't compare
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/src/test/ui/generic-associated-types/issue-87429-associated-type-default.stderr
new file mode 100644 (file)
index 0000000..01cb0bf
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0277]: can't compare `Foo` with `Foo`
+  --> $DIR/issue-87429-associated-type-default.rs:14:5
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo`
+   |
+   = help: the trait `PartialEq` is not implemented for `Foo`
+note: required by a bound in `Family2::Member`
+  --> $DIR/issue-87429-associated-type-default.rs:14:22
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>> = Foo;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.rs b/src/test/ui/generic-associated-types/issue-87429-specialization.rs
new file mode 100644 (file)
index 0000000..b365e07
--- /dev/null
@@ -0,0 +1,25 @@
+// check-fail
+
+#![feature(specialization)]
+//~^ WARN incomplete
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+}
+
+struct I32Family;
+
+impl Family for I32Family {
+    default type Member<'a> = i32;
+}
+
+struct Foo;
+struct FooFamily;
+
+impl Family for FooFamily {
+    default type Member<'a> = Foo;
+    //~^ ERROR can't compare
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
new file mode 100644 (file)
index 0000000..87bd35f
--- /dev/null
@@ -0,0 +1,26 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-87429-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+
+error[E0277]: can't compare `Foo` with `Foo`
+  --> $DIR/issue-87429-specialization.rs:21:5
+   |
+LL |     default type Member<'a> = Foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Foo == Foo`
+   |
+   = help: the trait `PartialEq` is not implemented for `Foo`
+note: required by a bound in `Family::Member`
+  --> $DIR/issue-87429-specialization.rs:8:22
+   |
+LL |     type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/generic-associated-types/issue-87429.rs b/src/test/ui/generic-associated-types/issue-87429.rs
new file mode 100644 (file)
index 0000000..f905348
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Family {
+    type Member<'a>: for<'b> PartialEq<Self::Member<'b>>;
+}
+
+struct I32;
+
+impl Family for I32 {
+    type Member<'a> = i32;
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs
new file mode 100644 (file)
index 0000000..93c3b39
--- /dev/null
@@ -0,0 +1,30 @@
+// Checks that we properly add implied bounds from unnormalized projections in
+// inputs when typechecking functions.
+
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait MyTrait {
+    type Assoc<'a, 'b> where 'b: 'a;
+    fn do_sth(arg: Self::Assoc<'_, '_>);
+}
+
+struct A;
+struct B;
+struct C;
+
+impl MyTrait for A {
+    type Assoc<'a, 'b> where 'b: 'a = u32;
+    fn do_sth(_: u32) {}
+}
+impl MyTrait for B {
+    type Assoc<'a, 'b> where 'b: 'a = u32;
+    fn do_sth(_: Self::Assoc<'_, '_>) {}
+}
+impl MyTrait for C {
+    type Assoc<'a, 'b> where 'b: 'a = u32;
+    fn do_sth(_: Self::Assoc<'static, 'static>) {}
+}
+
+fn main () {}
index 5e7e72ca562dd62067f807634203787c995bd355..2b57c439fe9a026057815233558d1cf5512e6a1e 100644 (file)
@@ -4,11 +4,11 @@ error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `Foo::Item`
-  --> $DIR/projection-bound-cycle-generic.rs:11:49
+note: required by a bound in `OnlySized`
+  --> $DIR/projection-bound-cycle-generic.rs:28:18
    |
-LL |     type Item: Sized where <Self as Foo>::Item: Sized;
-   |                                                 ^^^^^ required by this bound in `Foo::Item`
+LL | struct OnlySized<T> where T: Sized { f: T }
+   |                  ^ required by this bound in `OnlySized`
 
 error: aborting due to previous error
 
index 1153bf53ba43ed187298df8f28c756c1da6a633a..d9d0bf4274bd72c2f35ed75ea9053881260c36fb 100644 (file)
@@ -4,11 +4,11 @@ error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
 LL |     type Assoc = OnlySized<<T as Foo>::Item>;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required by a bound in `Foo::Item`
-  --> $DIR/projection-bound-cycle.rs:13:49
+note: required by a bound in `OnlySized`
+  --> $DIR/projection-bound-cycle.rs:30:18
    |
-LL |     type Item: Sized where <Self as Foo>::Item: Sized;
-   |                                                 ^^^^^ required by this bound in `Foo::Item`
+LL | struct OnlySized<T> where T: Sized { f: T }
+   |                  ^ required by this bound in `OnlySized`
 
 error: aborting due to previous error
 
index 41a0a03ff6688ea8f1d943b5a55b3bda2d8bb994..ab09ebcae71973ca7840d47c3b86079126ff7119 100644 (file)
@@ -5,7 +5,7 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.rs
new file mode 100644 (file)
index 0000000..24ac566
--- /dev/null
@@ -0,0 +1,88 @@
+// FamilyType (GAT workaround)
+pub trait FamilyLt<'a> {
+    type Out;
+}
+
+struct RefMutFamily<T>(std::marker::PhantomData<T>, ());
+impl<'a, T: 'a> FamilyLt<'a> for RefMutFamily<T> {
+    type Out = &'a mut T;
+}
+
+pub trait Execute {
+    type E: Inject;
+    fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out);
+}
+
+pub trait Inject
+where
+    Self: Sized,
+{
+    type I: for<'a> FamilyLt<'a>;
+    fn inject(_: &()) -> <Self::I as FamilyLt>::Out;
+}
+
+impl<T: 'static> Inject for RefMutFamily<T> {
+    type I = Self;
+    fn inject(_: &()) -> <Self::I as FamilyLt>::Out {
+        unimplemented!()
+    }
+}
+
+// This struct is only used to give a hint to the compiler about the type `Q`
+struct Annotate<Q>(std::marker::PhantomData<Q>);
+impl<Q> Annotate<Q> {
+    fn new() -> Self {
+        Self(std::marker::PhantomData)
+    }
+}
+
+// This function annotate a closure so it can have Higher-Rank Lifetime Bounds
+//
+// See 'annotate' workaround: https://github.com/rust-lang/rust/issues/58052
+fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
+where
+    F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
+    Q: Inject + 'static,
+{
+    let wrapper: Wrapper<Q, F> = Wrapper(std::marker::PhantomData, func);
+    wrapper
+}
+
+struct Wrapper<Q, F>(std::marker::PhantomData<Q>, F);
+impl<Q, F> Execute for Wrapper<Q, F>
+    where
+        Q: Inject,
+        F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out),
+{
+    type E = Q;
+
+    fn execute(self, value: <<Self::E as Inject>::I as FamilyLt>::Out) {
+        (self.1)(value)
+    }
+}
+
+struct Task {
+    _processor: Box<dyn FnOnce()>,
+}
+
+// This function consume the closure
+fn task<P>(processor: P) -> Task
+where P: Execute + 'static {
+    Task {
+        _processor: Box::new(move || {
+            let q = P::E::inject(&());
+            processor.execute(q);
+        })
+    }
+}
+
+fn main() {
+    task(annotate( //~ type mismatch
+        //~^ 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
new file mode 100644 (file)
index 0000000..8311c14
--- /dev/null
@@ -0,0 +1,67 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-62529-1.rs:80:10
+   |
+LL |     task(annotate(
+   |          ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
+...
+LL |         |value: &mut usize| {
+   |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+   |
+note: required by a bound in `annotate`
+  --> $DIR/issue-62529-1.rs:44:8
+   |
+LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
+   |    -------- required by a bound in this
+LL | where
+LL |     F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
+
+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(
+   |  __________^
+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(
+   |  __________^
+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 3 previous errors
+
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-2.rs
new file mode 100644 (file)
index 0000000..0020547
--- /dev/null
@@ -0,0 +1,33 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+trait Lt<'a> {
+    type T;
+}
+struct Id<T>(PhantomData<T>);
+impl<'a,T> Lt<'a> for Id<T> {
+    type T = T;
+}
+
+struct Ref<T>(PhantomData<T>) where T: ?Sized;
+impl<'a,T> Lt<'a> for Ref<T>
+where T: 'a + Lt<'a> + ?Sized
+{
+    type T = &'a T;
+}
+struct Mut<T>(PhantomData<T>) where T: ?Sized;
+impl<'a,T> Lt<'a> for Mut<T>
+where T: 'a + Lt<'a> + ?Sized
+{
+    type T = &'a mut T;
+}
+
+struct C<I,O>(for<'a> fn(<I as Lt<'a>>::T) -> O) where I: for<'a> Lt<'a>;
+
+
+fn main() {
+    let c = C::<Id<_>,_>(|()| 3);
+    c.0(());
+
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.rs
new file mode 100644 (file)
index 0000000..d84e30f
--- /dev/null
@@ -0,0 +1,32 @@
+trait ATC<'a> {
+    type Type: Sized;
+}
+
+trait WithDefault: for<'a> ATC<'a> {
+    fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F);
+}
+
+fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>(
+    f: F,
+    x: <T as ATC<'b>>::Type,
+) {
+    f(x);
+}
+
+impl<'a> ATC<'a> for () {
+    type Type = Self;
+}
+
+impl WithDefault for () {
+    fn with_default<F: for<'a> Fn(<Self as ATC<'a>>::Type)>(f: F) {
+        // Errors with a bogus type mismatch.
+        //f(());
+        // Going through another generic function works fine.
+        call(f, ());
+        //~^ expected a
+    }
+}
+
+fn main() {
+    // <()>::with_default(|_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
new file mode 100644 (file)
index 0000000..b110734
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+  --> $DIR/issue-62529-3.rs:25:9
+   |
+LL |         call(f, ());
+   |         ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+   |
+note: required by a bound in `call`
+  --> $DIR/issue-62529-3.rs:9:36
+   |
+LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(<T as ATC<'a>>::Type)>(
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-4.rs
new file mode 100644 (file)
index 0000000..8c2a598
--- /dev/null
@@ -0,0 +1,39 @@
+// check-pass
+
+use std::marker::PhantomData;
+use std::mem;
+
+trait Container<'a> {
+    type Root: 'a;
+}
+
+type RootOf<'a, T> = <T as Container<'a>>::Root;
+
+struct Test<'a, T> where T: Container<'a> {
+    pub root: T::Root,
+    marker: PhantomData<&'a mut &'a mut ()>,
+}
+
+impl<'a, 'b> Container<'b> for &'a str {
+    type Root = &'b str;
+}
+
+impl<'a, T> Test<'a, T> where T: for<'b> Container<'b> {
+    fn new(root: RootOf<'a, T>) -> Test<'a, T> {
+        Test {
+            root: root,
+            marker: PhantomData
+        }
+    }
+
+    fn with_mut<F, R>(&mut self, f: F) -> R where
+            F: for<'b> FnOnce(&'b mut RootOf<'b, T>) -> R {
+        f(unsafe { mem::transmute(&mut self.root) })
+    }
+}
+
+fn main() {
+    let val = "root";
+    let mut test: Test<&str> = Test::new(val);
+    test.with_mut(|_| { });
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-5.rs
new file mode 100644 (file)
index 0000000..03f257a
--- /dev/null
@@ -0,0 +1,27 @@
+// check-pass
+
+pub struct Struct {}
+
+pub trait Trait<'a> {
+    type Assoc;
+
+    fn method() -> Self::Assoc;
+}
+
+impl<'a> Trait<'a> for Struct {
+    type Assoc = ();
+
+    fn method() -> Self::Assoc {}
+}
+
+pub fn function<F, T>(f: F)
+where
+    F: for<'a> FnOnce(<T as Trait<'a>>::Assoc),
+    T: for<'b> Trait<'b>,
+{
+    f(T::method());
+}
+
+fn main() {
+    function::<_, Struct>(|_| {});
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-6.rs
new file mode 100644 (file)
index 0000000..74a4785
--- /dev/null
@@ -0,0 +1,77 @@
+// check-pass
+
+use std::cell::RefMut;
+
+fn main() {
+    StateMachine2::Init.resume();
+}
+
+enum StateMachine2<'a> {
+    Init,
+    #[allow(dead_code)] // match required for ICE
+    AfterTwoYields {
+        p: Backed<'a, *mut String>,
+    },
+}
+
+impl<'a> StateMachine2<'a> {
+    fn take(&self) -> Self {
+        StateMachine2::Init
+    }
+}
+
+impl<'a> StateMachine2<'a> {
+    fn resume(&mut self) -> () {
+        use StateMachine2::*;
+        match self.take() {
+            AfterTwoYields { p } => {
+                p.with(|_| {});
+            }
+            _ => panic!("Resume after completed."),
+        }
+    }
+}
+
+unsafe trait Unpack<'a> {
+    type Unpacked: 'a;
+
+    fn unpack(&self) -> Self::Unpacked {
+        unsafe { std::mem::transmute_copy(&self) }
+    }
+}
+
+unsafe trait Pack {
+    type Packed;
+
+    fn pack(&self) -> Self::Packed {
+        unsafe { std::mem::transmute_copy(&self) }
+    }
+}
+
+unsafe impl<'a> Unpack<'a> for String {
+    type Unpacked = String;
+}
+
+unsafe impl Pack for String {
+    type Packed = String;
+}
+
+unsafe impl<'a> Unpack<'a> for *mut String {
+    type Unpacked = &'a mut String;
+}
+
+unsafe impl<'a> Pack for &'a mut String {
+    type Packed = *mut String;
+}
+
+struct Backed<'a, U>(RefMut<'a, Option<String>>, U);
+
+impl<'a, 'b, U: Unpack<'b>> Backed<'a, U> {
+    fn with<F>(self, f: F) -> Backed<'a, ()>
+    where
+        F: for<'f> FnOnce(<U as Unpack<'f>>::Unpacked) -> (),
+    {
+        let result = f(self.1.unpack());
+        Backed(self.0, result)
+    }
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.rs
new file mode 100644 (file)
index 0000000..87d1a25
--- /dev/null
@@ -0,0 +1,29 @@
+pub trait MyTrait<'a> {
+    type Output: 'a;
+    fn gimme_value(&self) -> Self::Output;
+}
+
+pub struct MyStruct;
+
+impl<'a> MyTrait<'a> for MyStruct {
+    type Output = &'a usize;
+    fn gimme_value(&self) -> Self::Output {
+        unimplemented!()
+    }
+}
+
+fn meow<T, F>(t: T, f: F)
+where
+    T: for<'any> MyTrait<'any>,
+    F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
+{
+    let v = t.gimme_value();
+    f(v);
+}
+
+fn main() {
+    let struc = MyStruct;
+    meow(struc, |foo| { //~ type mismatch
+        println!("{:?}", foo);
+    })
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-70120.stderr
new file mode 100644 (file)
index 0000000..efc9568
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-70120.rs:26:5
+   |
+LL |     meow(struc, |foo| {
+   |     ^^^^        ----- found signature of `for<'r> fn(&'r usize) -> _`
+   |     |
+   |     expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _`
+   |
+note: required by a bound in `meow`
+  --> $DIR/issue-70120.rs:18:8
+   |
+LL | fn meow<T, F>(t: T, f: F)
+   |    ---- required by a bound in this
+...
+LL |     F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80706.rs
new file mode 100644 (file)
index 0000000..112227c
--- /dev/null
@@ -0,0 +1,70 @@
+// check-pass
+// edition:2018
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output=T>>>;
+
+fn main() {
+    f();
+}
+
+async fn f() {
+    run("dependency").await;
+}
+
+struct InMemoryStorage;
+
+struct User<'dep> {
+    dep: &'dep str,
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+    fn execute(&self) -> BoxFuture<Result<(), String>> {
+        todo!()
+    }
+}
+
+trait Storage {
+    type Error;
+}
+
+impl Storage for InMemoryStorage {
+    type Error = String;
+}
+
+trait StorageRequestReturnType {
+    type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+    fn execute(
+        &self,
+    ) -> BoxFuture<Result<<Self as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+struct SaveUser<'a> {
+    name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+    type Output = ();
+}
+
+impl<'dep> User<'dep> {
+    async fn save<S>(self)
+    where
+        S: Storage,
+        for<'a> SaveUser<'a>: StorageRequest<S>,
+    {
+        SaveUser { name: "Joe" }
+            .execute()
+            .await;
+    }
+}
+
+async fn run<S>(dep: &str)
+where
+    S: Storage,
+    for<'a> SaveUser<'a>: StorageRequest<S>,
+{
+    User { dep }.save().await;
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-80956.rs
new file mode 100644 (file)
index 0000000..6316cee
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+trait Bar {
+    type Type;
+}
+struct Foo<'a>(&'a ());
+impl<'a> Bar for Foo<'a> {
+    type Type = ();
+}
+
+fn func<'a>(_: <Foo<'a> as Bar>::Type) {}
+fn assert_is_func<A>(_: fn(A)) {}
+
+fn test()
+where
+    for<'a> <Foo<'a> as Bar>::Type: Sized,
+{
+    assert_is_func(func);
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-81809.rs
new file mode 100644 (file)
index 0000000..f6ab9c2
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+
+pub trait Indexable {
+    type Idx;
+}
+impl Indexable for u8 {
+    type Idx = u8;
+}
+impl Indexable for u16 {
+    type Idx = u16;
+}
+
+pub trait Indexer<T: Indexable>: std::ops::Index<T::Idx, Output = T> {}
+
+trait StoreIndex: Indexer<u8> + Indexer<u16> {}
+
+fn foo(st: &impl StoreIndex) -> &dyn StoreIndex {
+    st as &dyn StoreIndex
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
new file mode 100644 (file)
index 0000000..3a4d6c0
--- /dev/null
@@ -0,0 +1,18 @@
+#![feature(unboxed_closures)]
+
+trait SomeTrait<'a> {
+    type Associated;
+}
+
+fn give_me_ice<T>() {
+    callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
+    //~^ ERROR: the trait bound `T: SomeTrait<'_>` is not satisfied
+}
+
+fn callee<T: Fn<(&'static (),)>>() {
+    println!("{}", std::any::type_name::<<T as FnOnce<(&'static (),)>>::Output>());
+}
+
+fn main() {
+    give_me_ice::<()>();
+}
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
new file mode 100644 (file)
index 0000000..aaf45dc
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `T: SomeTrait<'_>` is not satisfied
+  --> $DIR/issue-85455.rs:8:5
+   |
+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 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/hrtb/due-to-where-clause.nll.stderr b/src/test/ui/hrtb/due-to-where-clause.nll.stderr
deleted file mode 100644 (file)
index 90803a0..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: higher-ranked subtype error
-  --> $DIR/due-to-where-clause.rs:2:5
-   |
-LL |     test::<FooS>(&mut 42);
-   |     ^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.nll.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.nll.stderr
deleted file mode 100644 (file)
index 4de35d7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: higher-ranked subtype error
-  --> $DIR/hrtb-cache-issue-54302.rs:19:5
-   |
-LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
index a812282def9a80835779b90b0707d81e9eb2b2fa..17d59bb321a453436bbbd8973e936846a8ac75cf 100644 (file)
@@ -17,11 +17,14 @@ LL |     want_hrtb::<&'a u32>()
    |
    = help: consider replacing `'a` with `'static`
 
-error: higher-ranked subtype error
+error: implementation of `Foo` is not general enough
   --> $DIR/hrtb-just-for-static.rs:30:5
    |
 LL |     want_hrtb::<&'a u32>()
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
+   |
+   = note: `Foo<&'0 isize>` would have to be implemented for the type `&u32`, for any lifetime `'0`...
+   = note: ...but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1`
 
 error: aborting due to 3 previous errors
 
index 7b81beeed4167de4932195f63eeb64b4359c3182..97f53bc70e44eeef6feea6ca9d9afd13fd83aa10 100644 (file)
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (<Unit2 as Ty<'r>>::V,)>>::O == <_ as Ty<'r>>::V`
+error[E0271]: type mismatch resolving `for<'r> <L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]> as T0<'r, (&'r u8,)>>::O == <_ as Ty<'r>>::V`
   --> $DIR/issue-62203-hrtb-ice.rs:38:19
    |
 LL |     let v = Unit2.m(
@@ -9,13 +9,13 @@ LL |     let v = Unit2.m(
    = help: consider constraining the associated type `<_ as Ty<'_>>::V` to `Unit4`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error[E0271]: type mismatch resolving `<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&u8,),)>>::Output == Unit3`
+error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39] as FnOnce<((&'r u8,),)>>::Output == Unit3`
   --> $DIR/issue-62203-hrtb-ice.rs:38:19
    |
 LL |     let v = Unit2.m(
    |                   ^ expected struct `Unit4`, found struct `Unit3`
    |
-note: required because of the requirements on the impl of `for<'r> T0<'r, (<Unit2 as Ty<'r>>::V,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>`
+note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:17: 42:39]>`
   --> $DIR/issue-62203-hrtb-ice.rs:17:16
    |
 LL | impl<'a, A, T> T0<'a, A> for L<T>
index d319ae6403fc5d709bc093d5be237981b47b196a..3b6216c3e63721d9c495b6aa81605ddd99900d0f 100644 (file)
@@ -3,8 +3,7 @@
 // check-pass
 // ignore-pretty pretty-printing is unhygienic
 
-#![feature(decl_macro, rustc_attrs, const_generics)]
-//~^ WARNING the feature `const_generics` is incomplete
+#![feature(decl_macro, rustc_attrs)]
 
 mod type_params {
     macro m($T:ident) {
diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr
deleted file mode 100644 (file)
index 4ca6d19..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_params.rs:6:37
-   |
-LL | #![feature(decl_macro, rustc_attrs, const_generics)]
-   |                                     ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 81e9b1b36e0641a8a5c1f5cadb51122f2fadda75..3634ee004f7f71d89a3fb88af53e66e55d14ad78 100644 (file)
@@ -3,8 +3,6 @@
 
 // check-pass
 
-#![feature(const_generics)] //~ WARNING `const_generics` is incomplete
-
 use std::ops::Add;
 
 struct VectorLike<T, const SIZE: usize>([T; {SIZE}]);
diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr
deleted file mode 100644 (file)
index b351b8b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61574-const-parameters.rs:6:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
index 4f49b3106edc405b9b3c709d368f25f16ae3d035..0e9b63d6370d6738d2d3c51d9cdff0baea1077a9 100644 (file)
@@ -23,9 +23,11 @@ LL |         ().clone()
    |            ^^^^^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use std::clone::Clone;`
    = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use std::clone::Clone;
+   |
 
 error: aborting due to 2 previous errors
 
index f16bb80dbb8568dbf5897d24f0dfa3b2679eca0f..77ab6e589e07c00f7011a7bf38a5d21d6a34d79e 100644 (file)
@@ -11,9 +11,11 @@ LL |     pub macro m() { ().f() }
    |                        ^ method not found in `()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use foo::T;`
    = note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use foo::T;
+   |
 
 error: aborting due to previous error
 
index 3eb141cc2bb55276341e1b22549c3aa553c0fb74..a31c104d8f58bb4db302e43f000cbf9aa19b7126 100644 (file)
@@ -30,10 +30,10 @@ note: ...which requires building MIR for `cycle1`...
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
+  --> $DIR/auto-trait-leak.rs:14:5
    |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     send(cycle2().clone());
+   |     ^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{opaque#0}`...
   --> $DIR/auto-trait-leak.rs:19:16
@@ -66,10 +66,10 @@ note: ...which requires building MIR for `cycle2`...
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
+  --> $DIR/auto-trait-leak.rs:20:5
    |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     send(cycle1().clone());
+   |     ^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
    = note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
 note: cycle used when checking item types in top-level module
index bf04a8c987393017a5755560c87a895cf3e51bf1..3c720f50d48b266b3327f5cf580267c7be27e6c7 100644 (file)
@@ -5,7 +5,7 @@ LL |     fn foo_fail<T: Trait>() -> impl FooLike<Output = T::Assoc> {
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
    = note: expected associated type `<T as impl_trait::Trait>::Assoc`
-                         found type `()`
+                    found unit type `()`
 help: consider constraining the associated type `<T as impl_trait::Trait>::Assoc` to `()`
    |
 LL |     fn foo_fail<T: Trait<Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
@@ -24,7 +24,7 @@ LL |     fn foo2_fail<'a, T: Trait<'a>>() -> impl FooLike<Output = T::Assoc> {
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `()`
    |
    = note: expected associated type `<T as lifetimes::Trait<'static>>::Assoc`
-                         found type `()`
+                    found unit type `()`
 help: consider constraining the associated type `<T as lifetimes::Trait<'static>>::Assoc` to `()`
    |
 LL |     fn foo2_fail<'a, T: Trait<'a, Assoc = ()>>() -> impl FooLike<Output = T::Assoc> {
diff --git a/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr b/src/test/ui/impl-trait/issue-55872-1.full_tait.stderr
deleted file mode 100644 (file)
index 50eab7d..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-55872-1.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0276]: impl has stricter requirements than trait
-  --> $DIR/issue-55872-1.rs:17:5
-   |
-LL |     fn foo<T>() -> Self::E;
-   |     ----------------------- definition of `foo` from trait
-...
-LL |     fn foo<T: Default>() -> Self::E {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `T: Default`
-
-error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:13:14
-   |
-LL |     type E = impl Copy;
-   |              ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S`
-   |
-   = note: required because it appears within the type `(S, T)`
-help: consider further restricting this bound
-   |
-LL | impl<S: Default + std::marker::Copy> Bar for S {
-   |                 +++++++++++++++++++
-
-error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:13:14
-   |
-LL |     type E = impl Copy;
-   |              ^^^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T`
-   |
-   = note: required because it appears within the type `(S, T)`
-help: consider further restricting this bound
-   |
-LL |     fn foo<T: Default + std::marker::Copy>() -> Self::E {
-   |                       +++++++++++++++++++
-
-error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/issue-55872-1.rs:17:37
-   |
-LL |       fn foo<T: Default>() -> Self::E {
-   |  _____________________________________^
-LL | |
-LL | |
-LL | |         (S::default(), T::default())
-LL | |     }
-   | |_____^
-
-error: aborting due to 4 previous errors; 1 warning emitted
-
-Some errors have detailed explanations: E0276, E0277.
-For more information about an error, try `rustc --explain E0276`.
index 121536d3f68574173338da6f9b91eadad43f0c21..394b697a2504b13cf6e2a3efe0dc6c8765b26907 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 = "2018"` in `Cargo.toml`
+   = help: set `edition = "2021"` in `Cargo.toml`
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0562]: `impl Trait` not allowed outside of function and method return types
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.stderr
deleted file mode 100644 (file)
index 4de872e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-warning[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
-  --> $DIR/inverse-bounds.rs:16:70
-   |
-LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e>
-   |                                                                      ^^^^^^^^^^^^^^^^^^
-   |
-   = note: hidden type `Invert<'_>` captures lifetime '_#8r
-   = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
-   = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
-   = note: for more information, try `rustc --explain E0729`
-
-warning: the feature `pin` has been stable since 1.33.0 and no longer requires an attribute to enable
-  --> $DIR/inverse-bounds.rs:4:60
-   |
-LL | #![feature(arbitrary_self_types, async_await, await_macro, pin)]
-   |                                                            ^^^
-   |
-   = note: #[warn(stable_features)] on by default
-
index 7ffb51061b7ddef30788e74da7c96cae47c0ede2..369645f9030fbc8c9d93fc4438e9a280fa671c12 100644 (file)
@@ -18,7 +18,7 @@ error[E0391]: cycle detected when computing drop-check constraints for `Take`
 LL | struct Take(Take);
    | ^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires computing drop-check constraints for `Take`, completing the cycle
+   = note: ...which immediately requires computing drop-check constraints for `Take` again
    = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: Take } }`
 
 error: aborting due to 2 previous errors
index 1f147e070b4d10cec588ac6d3b3dd92e208d49aa..61b5e9467752642487ab59618946c91f797f01a6 100644 (file)
@@ -17,7 +17,7 @@ error[E0391]: cycle detected when computing drop-check constraints for `MList`
 LL | enum MList { Cons(isize, MList), Nil }
    | ^^^^^^^^^^
    |
-   = note: ...which again requires computing drop-check constraints for `MList`, completing the cycle
+   = note: ...which immediately requires computing drop-check constraints for `MList` again
    = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: MList } }`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/infinite/infinite-trait-alias-recursion.rs b/src/test/ui/infinite/infinite-trait-alias-recursion.rs
new file mode 100644 (file)
index 0000000..ec86744
--- /dev/null
@@ -0,0 +1,10 @@
+#![feature(trait_alias)]
+
+trait T1 = T2;
+//~^ ERROR cycle detected when computing the super predicates of `T1`
+
+trait T2 = T3;
+
+trait T3 = T1 + T3;
+
+fn main() {}
diff --git a/src/test/ui/infinite/infinite-trait-alias-recursion.stderr b/src/test/ui/infinite/infinite-trait-alias-recursion.stderr
new file mode 100644 (file)
index 0000000..5ecaedb
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0391]: cycle detected when computing the super predicates of `T1`
+  --> $DIR/infinite-trait-alias-recursion.rs:3:1
+   |
+LL | trait T1 = T2;
+   | ^^^^^^^^^^^^^^
+   |
+note: ...which requires computing the super traits of `T1`...
+  --> $DIR/infinite-trait-alias-recursion.rs:3:12
+   |
+LL | trait T1 = T2;
+   |            ^^
+note: ...which requires computing the super predicates of `T2`...
+  --> $DIR/infinite-trait-alias-recursion.rs:6:1
+   |
+LL | trait T2 = T3;
+   | ^^^^^^^^^^^^^^
+note: ...which requires computing the super traits of `T2`...
+  --> $DIR/infinite-trait-alias-recursion.rs:6:12
+   |
+LL | trait T2 = T3;
+   |            ^^
+note: ...which requires computing the super predicates of `T3`...
+  --> $DIR/infinite-trait-alias-recursion.rs:8:1
+   |
+LL | trait T3 = T1 + T3;
+   | ^^^^^^^^^^^^^^^^^^^
+note: ...which requires computing the super traits of `T3`...
+  --> $DIR/infinite-trait-alias-recursion.rs:8:12
+   |
+LL | trait T3 = T1 + T3;
+   |            ^^
+   = note: ...which again requires computing the super predicates of `T1`, completing the cycle
+   = note: trait aliases cannot be recursive
+note: cycle used when collecting item types in top-level module
+  --> $DIR/infinite-trait-alias-recursion.rs:3:1
+   |
+LL | trait T1 = T2;
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.rs
new file mode 100644 (file)
index 0000000..5381eed
--- /dev/null
@@ -0,0 +1,6 @@
+type X1 = X2;
+//~^ ERROR cycle detected when expanding type alias `X1`
+type X2 = X3;
+type X3 = X1;
+
+fn main() {}
diff --git a/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr b/src/test/ui/infinite/infinite-type-alias-mutual-recursion.stderr
new file mode 100644 (file)
index 0000000..7f82b29
--- /dev/null
@@ -0,0 +1,34 @@
+error[E0391]: cycle detected when expanding type alias `X1`
+  --> $DIR/infinite-type-alias-mutual-recursion.rs:1:11
+   |
+LL | type X1 = X2;
+   |           ^^
+   |
+note: ...which requires expanding type alias `X2`...
+  --> $DIR/infinite-type-alias-mutual-recursion.rs:3:11
+   |
+LL | type X2 = X3;
+   |           ^^
+note: ...which requires expanding type alias `X3`...
+  --> $DIR/infinite-type-alias-mutual-recursion.rs:4:11
+   |
+LL | type X3 = X1;
+   |           ^^
+   = note: ...which again requires expanding type alias `X1`, completing the cycle
+   = note: type aliases cannot be recursive
+   = help: consider using a struct, enum, or union instead to break the cycle
+   = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
+note: cycle used when collecting item types in top-level module
+  --> $DIR/infinite-type-alias-mutual-recursion.rs:1:1
+   |
+LL | / type X1 = X2;
+LL | |
+LL | | type X2 = X3;
+LL | | type X3 = X1;
+LL | |
+LL | | fn main() {}
+   | |____________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
index 77adefeb124e355e2ec0482738e1a1f4631ed980..1e487a5b11c2af4eb287f5d208baaf47c8bbb9b7 100644 (file)
@@ -1,10 +1,13 @@
-error[E0391]: cycle detected when computing type of `X`
+error[E0391]: cycle detected when expanding type alias `X`
   --> $DIR/infinite-vec-type-recursion.rs:1:14
    |
 LL | type X = Vec<X>;
    |              ^
    |
-   = note: ...which again requires computing type of `X`, completing the cycle
+   = note: ...which immediately requires expanding type alias `X` again
+   = note: type aliases cannot be recursive
+   = help: consider using a struct, enum, or union instead to break the cycle
+   = help: see <https://doc.rust-lang.org/reference/types.html#recursive-types> for more information
 note: cycle used when collecting item types in top-level module
   --> $DIR/infinite-vec-type-recursion.rs:1:1
    |
diff --git a/src/test/ui/inline-const/const-match-pat-generic.rs b/src/test/ui/inline-const/const-match-pat-generic.rs
new file mode 100644 (file)
index 0000000..61680d6
--- /dev/null
@@ -0,0 +1,16 @@
+#![allow(incomplete_features)]
+#![feature(inline_const)]
+
+// rust-lang/rust#82518: ICE with inline-const in match referencing const-generic parameter
+
+fn foo<const V: usize>() {
+  match 0 {
+    const { V } => {},
+    //~^ ERROR const parameters cannot be referenced in patterns [E0158]
+    _ => {},
+  }
+}
+
+fn main() {
+    foo::<1>();
+}
diff --git a/src/test/ui/inline-const/const-match-pat-generic.stderr b/src/test/ui/inline-const/const-match-pat-generic.stderr
new file mode 100644 (file)
index 0000000..a3ed41a
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0158]: const parameters cannot be referenced in patterns
+  --> $DIR/const-match-pat-generic.rs:8:11
+   |
+LL |     const { V } => {},
+   |           ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0158`.
index eb32c8db3f6687b384c2d577eff99e555a257748..0ccf69dc0607615580af4d1ee77df8d12710ff69 100644 (file)
@@ -5,8 +5,10 @@ LL |             b.foo();
    |               ^^^ method not found in `&B`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use a::A;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |         use a::A;
+   |
 
 error: aborting due to previous error
 
index 93364d2f6259e7c01b8c31d4c1cd5fb90a301ec7..7400aadb059f70ddd41c43e9e36003e427712014 100644 (file)
@@ -15,8 +15,8 @@ fn drop(&mut self) {}
 fn main() {
     let foo = X(1);
     drop(foo);
-    match foo {
-        X(1) => (), //~ ERROR use of moved value
+    match foo { //~ ERROR use of moved value
+        X(1) => (),
         _ => unreachable!()
     }
 
index 28c22260c3888bf82c6516047cf01a588134ff8d..77aa201b33564722dda46b25b58ed918a9941b80 100644 (file)
@@ -1,13 +1,12 @@
 error[E0382]: use of moved value: `foo`
-  --> $DIR/issue-17385.rs:19:11
+  --> $DIR/issue-17385.rs:18:5
    |
 LL |     let foo = X(1);
    |         --- move occurs because `foo` has type `X`, which does not implement the `Copy` trait
 LL |     drop(foo);
    |          --- value moved here
 LL |     match foo {
-LL |         X(1) => (),
-   |           ^ value used here after move
+   |     ^^^^^^^^^ value used here after move
 
 error[E0382]: use of moved value: `e`
   --> $DIR/issue-17385.rs:25:11
index 4aecc7eab46287bfe9ad257c1080edc372e7d9db..c964dc41dceafece79bb65ab6295a9ce6bfd650d 100644 (file)
@@ -6,7 +6,7 @@ LL | |
 LL | | {}
    | |__^
    |
-   = note: ...which again requires computing the super traits of `T` with associated type name `Item`, completing the cycle
+   = note: ...which immediately requires computing the super traits of `T` with associated type name `Item` again
 note: cycle used when computing the super traits of `T`
   --> $DIR/issue-20772.rs:1:1
    |
index ccbe06d9c0d565a20d79ebc43394815692c49c4b..be2bbd448007b605ce3ea4e011a8ca592d16cf02 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing the super traits of `Processor` with
 LL | pub trait Processor: Subscriber<Input = Self::Input> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires computing the super traits of `Processor` with associated type name `Input`, completing the cycle
+   = note: ...which immediately requires computing the super traits of `Processor` with associated type name `Input` again
 note: cycle used when computing the super traits of `Processor`
   --> $DIR/issue-20825.rs:5:1
    |
index 59cc6550a8bd6bb0736fbcfb360911e2fe39656f..6877a18460509feb04badbd366a7701de10de779 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing the bounds for type parameter `T`
 LL | fn foo<T: Trait<A = T::B>>() { }
    |                     ^^^^
    |
-   = note: ...which again requires computing the bounds for type parameter `T`, completing the cycle
+   = note: ...which immediately requires computing the bounds for type parameter `T` again
 note: cycle used when computing explicit predicates of `foo`
   --> $DIR/issue-21177.rs:6:21
    |
index e8c1e8f9669731e963be73c8caea3eb3c8da995c..8be3cfa72fb2675afb8fc3ae7596ada986fcc77f 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing type of `Foo::T`
 LL | pub struct Foo<T = Box<Trait<DefaultFoo>>>;
    |                              ^^^^^^^^^^
    |
-note: ...which requires computing type of `DefaultFoo`...
+note: ...which requires expanding type alias `DefaultFoo`...
   --> $DIR/issue-34373.rs:8:19
    |
 LL | type DefaultFoo = Foo;
index fafef79ea5b866adf39ed4846dc792db57c14729..42cef9a47f2792deebb6fa59daf887b4f09589ea 100644 (file)
@@ -1,5 +1,3 @@
-// check-pass
-
 use std::mem;
 
 trait Trait1<T> {}
@@ -8,6 +6,7 @@ trait Trait2<'a> {
 }
 
 fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied
     let _e: (usize, usize) = unsafe{mem::transmute(param)};
 }
 
diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr
new file mode 100644 (file)
index 0000000..dda6145
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+  --> $DIR/issue-35570.rs:8:4
+   |
+LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+   |    ^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index 91e31ca0bd8b1d885b52b54c4e522a026a87b5e9..7626f827fc5ebb161f7eb0ca563b00311754443d 100644 (file)
@@ -5,7 +5,7 @@ LL |     entries: [T; D::dim()],
    |                  ^^^^^^ cannot perform const operation using `D`
    |
    = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to previous error
 
index 99cae46fd9cf2b9c33d7f0704ee44d6b0ba6e43f..cedcf7c361c3bbb6d32109c49be0aaa2c28adf72 100644 (file)
@@ -1,3 +1,5 @@
+// check-pass
+
 pub trait Trait<'a> {
     type Assoc;
 }
@@ -14,7 +16,6 @@ pub fn break_me<T, F>(f: F)
     F: for<'b> FnMut(<T as Trait<'b>>::Assoc),
 {
     break_me::<Type, fn(_)>;
-    //~^ ERROR: type mismatch in function arguments
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr
deleted file mode 100644 (file)
index b99f367..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0631]: type mismatch in function arguments
-  --> $DIR/issue-43623.rs:16:5
-   |
-LL |     break_me::<Type, fn(_)>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
-   |     found signature of `fn(()) -> _`
-   |
-note: required by a bound in `break_me`
-  --> $DIR/issue-43623.rs:14:16
-   |
-LL | pub fn break_me<T, F>(f: F)
-   |        -------- required by a bound in this
-...
-LL |     F: for<'b> FnMut(<T as Trait<'b>>::Assoc),
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `break_me`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
index 041fcdbf823bfcc36aab26f0907642f1e55f21d2..ab3b92142c8c986085aa920e96a69c9e2aacaa62 100644 (file)
@@ -1,4 +1,3 @@
-// build-pass
 pub trait Foo<'a> {
     type Bar;
     fn foo(&'a self) -> Self::Bar;
@@ -12,8 +11,9 @@ fn foo(&'a self) -> &'a T {
 }
 
 pub fn uncallable<T, F>(x: T, f: F)
-    where T: for<'a> Foo<'a>,
-          F: for<'a> Fn(<T as Foo<'a>>::Bar)
+where
+    T: for<'a> Foo<'a>,
+    F: for<'a> Fn(<T as Foo<'a>>::Bar),
 {
     f(x.foo());
 }
@@ -24,6 +24,7 @@ pub fn catalyst(x: &i32) {
 
 pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
     uncallable(x, |y| f(y));
+    //~^ type mismatch
 }
 
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/issues/issue-44005.stderr b/src/test/ui/issues/issue-44005.stderr
new file mode 100644 (file)
index 0000000..307e444
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0631]: type mismatch in closure arguments
+  --> $DIR/issue-44005.rs:26:5
+   |
+LL |     uncallable(x, |y| f(y));
+   |     ^^^^^^^^^^    -------- found signature of `for<'r> fn(&'r i32) -> _`
+   |     |
+   |     expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _`
+   |
+note: required by a bound in `uncallable`
+  --> $DIR/issue-44005.rs:16:8
+   |
+LL | pub fn uncallable<T, F>(x: T, f: F)
+   |        ---------- required by a bound in this
+...
+LL |     F: for<'a> Fn(<T as Foo<'a>>::Bar),
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
index cf95d309c63442d42fc605af7acb61b50a49f76b..a029948ca3b82bba510816c6dc1d7fdbd3c6dd3c 100644 (file)
@@ -1,15 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-47486.rs:3:31
+   |
+LL |     [0u8; std::mem::size_of::<_>()];
+   |                               ^ cannot infer type
+
 error[E0308]: mismatched types
   --> $DIR/issue-47486.rs:2:10
    |
 LL |     () < std::mem::size_of::<_>();
    |          ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-47486.rs:3:11
-   |
-LL |     [0u8; std::mem::size_of::<_>()];
-   |           ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0282, E0308.
diff --git a/src/test/ui/issues/issue-54302.nll.stderr b/src/test/ui/issues/issue-54302.nll.stderr
deleted file mode 100644 (file)
index e68de03..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: higher-ranked subtype error
-  --> $DIR/issue-54302.rs:13:5
-   |
-LL |     assert_deserialize_owned::<&'static str>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-57843.nll.stderr b/src/test/ui/issues/issue-57843.nll.stderr
deleted file mode 100644 (file)
index 2ab49ec..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/issue-57843.rs:25:9
-   |
-LL |     Foo(Box::new(|_| ()));
-   |         ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 bool)` must implement `FnOnce<(&'1 bool,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 bool,)>`, for some specific lifetime `'2`
-
-error: aborting due to previous error
-
index a687a9e3be12c4408857ff38eecc40d47d23a3c1..6376c429b287bf3b4592f04d10481cc7c4debdc6 100644 (file)
@@ -1,9 +1,8 @@
 #![allow(dead_code)]
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![feature(const_generics_defaults)]
 
 // This test checks that generic parameter re-ordering diagnostic suggestions mention that
-// consts come after types and lifetimes when the `const_generics` feature is enabled.
+// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
 // We cannot run rustfix on this test because of the above const generics warning.
 
 struct A;
index 5e97339f148c5cbcaa97e0140d240e1359296411..df244f02dce68e8aaccc3f5265491adb148d2b40 100644 (file)
@@ -1,17 +1,8 @@
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/issue-59508-1.rs:12:25
+  --> $DIR/issue-59508-1.rs:11:25
    |
 LL |     pub fn do_things<T, 'a, 'b: 'a>() {
    |                     ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
 
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-59508-1.rs:2:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
index a16363d7c87301725591df53690a03cc2e673a62..ac33cfd0402434095b36ca5b0fe27cd968077e5c 100644 (file)
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `for<'t> <Map<<&'t _ as IntoIterator>::IntoIter, _> as Iterator>::Item: Foo` is not satisfied
+error[E0277]: the trait bound `&u32: Foo` is not satisfied
   --> $DIR/issue-60218.rs:18:5
    |
 LL |     trigger_error(vec![], |x: &u32| x)
-   |     ^^^^^^^^^^^^^ the trait `for<'t> Foo` is not implemented for `<Map<<&'t _ as IntoIterator>::IntoIter, _> as Iterator>::Item`
+   |     ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
    |
 note: required by a bound in `trigger_error`
   --> $DIR/issue-60218.rs:13:72
index 036a9300a174db33de6bd5f16cf1204aa2375fb8..733456a1a8bd1b22751c39944b4bc98d4e617dc2 100644 (file)
@@ -4,8 +4,8 @@ error[E0271]: type mismatch resolving `<Rc<Apple> as Deref>::Target == Rc<Apple>
 LL |     let _ = Pin::new(Apple) == Rc::pin(Apple);
    |                             ^^ expected struct `Apple`, found struct `Rc`
    |
-   = note: expected type `Apple`
-            found struct `Rc<Apple>`
+   = note: expected struct `Apple`
+              found struct `Rc<Apple>`
    = note: required because of the requirements on the impl of `PartialEq<Pin<Rc<Apple>>>` for `Pin<Apple>`
 
 error: aborting due to previous error
index 928fa58b17556d14833373819cf477705c7b5247..05650f05cbf5b24b94fbde014dc456705f0529cf 100644 (file)
@@ -19,13 +19,13 @@ LL |         Binder(_a, _x @ ..) => {}
    = note: only allowed in tuple, tuple struct, and slice patterns
 
 error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/issue-72574-2.rs:6:9
+  --> $DIR/issue-72574-2.rs:6:16
    |
 LL | struct Binder(i32, i32, i32);
-   | ----------------------------- tuple struct defined here
+   |               ---  ---  --- tuple struct has 3 fields
 ...
 LL |         Binder(_a, _x @ ..) => {}
-   |         ^^^^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |                ^^  ^^^^^^^ expected 3 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/issues/issue-83190.rs b/src/test/ui/issues/issue-83190.rs
new file mode 100644 (file)
index 0000000..da931c3
--- /dev/null
@@ -0,0 +1,49 @@
+// check-pass
+
+// Regression test for issue #83190, triggering an ICE in borrowck.
+
+pub trait Any {}
+impl<T> Any for T {}
+
+pub trait StreamOnce {
+    type Range;
+}
+
+pub trait Parser<Input>: Sized {
+    type Output;
+    type PartialState;
+    fn map(self) -> Map<Self> {
+        todo!()
+    }
+}
+
+pub struct Map<P>(P);
+impl<I, P: Parser<I, Output = ()>> Parser<I> for Map<P> {
+    type Output = ();
+    type PartialState = P::PartialState;
+}
+
+struct TakeWhile1<Input>(Input);
+impl<I: StreamOnce> Parser<I> for TakeWhile1<I> {
+    type Output = I::Range;
+    type PartialState = ();
+}
+impl<I> TakeWhile1<I> {
+    fn new() -> Self {
+        todo!()
+    }
+}
+
+impl<I, A: Parser<I>> Parser<I> for (A,) {
+    type Output = ();
+    type PartialState = Map<A::Output>;
+}
+
+pub fn metric_stream_parser<'a, I>() -> impl Parser<I, Output = (), PartialState = impl Any + 'a>
+where
+    I: StreamOnce<Range = &'a [()]>,
+{
+    (TakeWhile1::new(),).map()
+}
+
+fn main() {}
index e56c2956a697e8fa21cbe738168eb2c8ea188a16..60995170a5164397b459ca6c0df73e865863fd50 100644 (file)
@@ -19,9 +19,12 @@ fn main() {
     //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
     //~| WARNING this changes meaning
 
-    // The `array_into_iter` lint doesn't cover other wrappers that deref to an array.
     let _: Iter<'_, i32> = Rc::new(array).into_iter();
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
     let _: Iter<'_, i32> = Array(array).into_iter();
+    //~^ WARNING this method call resolves to `<&[T; N] as IntoIterator>::into_iter`
+    //~| WARNING this changes meaning
 
     // But you can always use the trait method explicitly as an array.
     let _: IntoIter<i32, 10> = IntoIterator::into_iter(array);
index e9780d9b165c765239b84e22641bf7e8f729ca16..bc08fdcafa08d3dcc249e7c55e8b365cf848e373 100644 (file)
@@ -20,21 +20,31 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
   --> $DIR/into-iter-on-arrays-2018.rs:18:44
    |
 LL |     let _: Iter<'_, i32> = Box::new(array).into_iter();
-   |                                            ^^^^^^^^^
+   |                                            ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
+
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-2018.rs:22:43
    |
-LL |     let _: Iter<'_, i32> = Box::new(array).iter();
-   |                                            ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
+LL |     let _: Iter<'_, i32> = Rc::new(array).into_iter();
+   |                                           ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |
+   = warning: this changes meaning in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
+
+warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
+  --> $DIR/into-iter-on-arrays-2018.rs:25:41
    |
-LL |     let _: Iter<'_, i32> = IntoIterator::into_iter(Box::new(array));
-   |                            ++++++++++++++++++++++++               ~
+LL |     let _: Iter<'_, i32> = Array(array).into_iter();
+   |                                         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
+   |
+   = warning: this changes meaning in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
-  --> $DIR/into-iter-on-arrays-2018.rs:29:24
+  --> $DIR/into-iter-on-arrays-2018.rs:32:24
    |
 LL |     for _ in [1, 2, 3].into_iter() {}
    |                        ^^^^^^^^^
@@ -51,5 +61,5 @@ LL -     for _ in [1, 2, 3].into_iter() {}
 LL +     for _ in [1, 2, 3] {}
    | 
 
-warning: 3 warnings emitted
+warning: 5 warnings emitted
 
index 138becc4ffe1ea6cca92202c562eb708ce8cc96c..2df1a06df20ab027ad6e9e49be526149e87ec8ff 100644 (file)
@@ -71,137 +71,73 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
   --> $DIR/into-iter-on-arrays-lint.rs:23:21
    |
 LL |     Box::new(small).into_iter();
-   |                     ^^^^^^^^^
+   |                     ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(small).iter();
-   |                     ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(small));
-   |     ++++++++++++++++++++++++               ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:26:22
    |
 LL |     Box::new([1, 2]).into_iter();
-   |                      ^^^^^^^^^
+   |                      ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new([1, 2]).iter();
-   |                      ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new([1, 2]));
-   |     ++++++++++++++++++++++++                ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:29:19
    |
 LL |     Box::new(big).into_iter();
-   |                   ^^^^^^^^^
+   |                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(big).iter();
-   |                   ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(big));
-   |     ++++++++++++++++++++++++             ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:32:25
    |
 LL |     Box::new([0u8; 33]).into_iter();
-   |                         ^^^^^^^^^
+   |                         ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new([0u8; 33]).iter();
-   |                         ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new([0u8; 33]));
-   |     ++++++++++++++++++++++++                   ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:36:31
    |
 LL |     Box::new(Box::new(small)).into_iter();
-   |                               ^^^^^^^^^
+   |                               ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(Box::new(small)).iter();
-   |                               ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(Box::new(small)));
-   |     ++++++++++++++++++++++++                         ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:39:32
    |
 LL |     Box::new(Box::new([1, 2])).into_iter();
-   |                                ^^^^^^^^^
+   |                                ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(Box::new([1, 2])).iter();
-   |                                ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(Box::new([1, 2])));
-   |     ++++++++++++++++++++++++                          ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:42:29
    |
 LL |     Box::new(Box::new(big)).into_iter();
-   |                             ^^^^^^^^^
+   |                             ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(Box::new(big)).iter();
-   |                             ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(Box::new(big)));
-   |     ++++++++++++++++++++++++                       ~
 
 warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <[T; N] as IntoIterator>::into_iter in Rust 2021.
   --> $DIR/into-iter-on-arrays-lint.rs:45:35
    |
 LL |     Box::new(Box::new([0u8; 33])).into_iter();
-   |                                   ^^^^^^^^^
+   |                                   ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
    |
    = warning: this changes meaning in Rust 2021
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
-help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
-   |
-LL |     Box::new(Box::new([0u8; 33])).iter();
-   |                                   ~~~~
-help: or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value
-   |
-LL |     IntoIterator::into_iter(Box::new(Box::new([0u8; 33])));
-   |     ++++++++++++++++++++++++                             ~
 
 warning: 12 warnings emitted
 
diff --git a/src/test/ui/lang-items/lang-item-correct-generics.rs b/src/test/ui/lang-items/lang-item-correct-generics.rs
new file mode 100644 (file)
index 0000000..a3287db
--- /dev/null
@@ -0,0 +1,28 @@
+// build-pass
+
+#![feature(lang_items,no_core)]
+#![no_core]
+#![crate_type="lib"]
+
+#[lang = "sized"]
+trait MySized {}
+
+#[lang = "copy"]
+trait MyCopy {}
+
+#[lang = "drop"]
+trait MyDrop<T> {}
+
+struct S;
+
+impl<T> MyDrop<T> for S {}
+
+#[lang = "i32"]
+impl<'a> i32 {
+    fn foo() {}
+}
+
+fn bar() {
+    i32::foo();
+    S;
+}
diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.rs b/src/test/ui/lang-items/lang-item-generic-requirements.rs
new file mode 100644 (file)
index 0000000..d785749
--- /dev/null
@@ -0,0 +1,44 @@
+// Checks whether declaring a lang item with the wrong number
+// of generic arguments crashes the compiler (issue #83893, #87573, and part of #9307).
+
+#![feature(lang_items, no_core)]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait MySized {}
+
+#[lang = "add"]
+trait MyAdd<'a, T> {}
+//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718]
+
+#[lang = "drop_in_place"]
+//~^ ERROR `drop_in_place` language item must be applied to a function with at least 1 generic
+fn my_ptr_drop() {}
+
+#[lang = "index"]
+trait MyIndex<'a, T> {}
+//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718]
+
+#[lang = "phantom_data"]
+//~^ ERROR `phantom_data` language item must be applied to a struct with 1 generic argument
+struct MyPhantomData<T, U>;
+//~^ ERROR parameter `T` is never used
+//~| ERROR parameter `U` is never used
+
+fn ice() {
+    // Use add
+    let r = 5;
+    let a = 6;
+    r + a;
+
+    // Use drop in place
+    my_ptr_drop();
+
+    // Use index
+    let arr = [0; 5];
+    let _ = arr[2];
+
+    // Use phantomdata
+    let _ = MyPhantomData::<(), i32>;
+}
diff --git a/src/test/ui/lang-items/lang-item-generic-requirements.stderr b/src/test/ui/lang-items/lang-item-generic-requirements.stderr
new file mode 100644 (file)
index 0000000..add5938
--- /dev/null
@@ -0,0 +1,56 @@
+error[E0718]: `add` language item must be applied to a trait with 1 generic argument
+  --> $DIR/lang-item-generic-requirements.rs:11:1
+   |
+LL | #[lang = "add"]
+   | ^^^^^^^^^^^^^^^
+LL | trait MyAdd<'a, T> {}
+   |            ------- this trait has 2 generic arguments
+
+error[E0718]: `drop_in_place` language item must be applied to a function with at least 1 generic argument
+  --> $DIR/lang-item-generic-requirements.rs:15:1
+   |
+LL | #[lang = "drop_in_place"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn my_ptr_drop() {}
+   |               - this function has 0 generic arguments
+
+error[E0718]: `index` language item must be applied to a trait with 1 generic argument
+  --> $DIR/lang-item-generic-requirements.rs:19:1
+   |
+LL | #[lang = "index"]
+   | ^^^^^^^^^^^^^^^^^
+LL | trait MyIndex<'a, T> {}
+   |              ------- this trait has 2 generic arguments
+
+error[E0718]: `phantom_data` language item must be applied to a struct with 1 generic argument
+  --> $DIR/lang-item-generic-requirements.rs:23:1
+   |
+LL | #[lang = "phantom_data"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct MyPhantomData<T, U>;
+   |                     ------ this struct has 2 generic arguments
+
+error[E0392]: parameter `T` is never used
+  --> $DIR/lang-item-generic-requirements.rs:25:22
+   |
+LL | struct MyPhantomData<T, U>;
+   |                      ^ unused parameter
+   |
+   = help: consider removing `T` or referring to it in a field
+   = help: if you intended `T` to be a const parameter, use `const T: usize` instead
+
+error[E0392]: parameter `U` is never used
+  --> $DIR/lang-item-generic-requirements.rs:25:25
+   |
+LL | struct MyPhantomData<T, U>;
+   |                         ^ unused parameter
+   |
+   = help: consider removing `U` or referring to it in a field
+   = help: if you intended `U` to be a const parameter, use `const U: usize` instead
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0392, E0718.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/src/test/ui/lang-items/wrong-number-generic-args-add.rs b/src/test/ui/lang-items/wrong-number-generic-args-add.rs
deleted file mode 100644 (file)
index 9f4f246..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// Checks whether declaring a lang item with the wrong number
-// of generic arguments crashes the compiler (issue #83893).
-
-#![feature(lang_items,no_core)]
-#![no_core]
-#![crate_type="lib"]
-
-#[lang = "sized"]
-trait MySized {}
-
-#[lang = "add"]
-trait MyAdd<'a, T> {}
-//~^^ ERROR: `add` language item must be applied to a trait with 1 generic argument [E0718]
-
-fn ice() {
-    let r = 5;
-    let a = 6;
-    r + a
-    //~^ ERROR: cannot add `{integer}` to `{integer}` [E0369]
-}
diff --git a/src/test/ui/lang-items/wrong-number-generic-args-add.stderr b/src/test/ui/lang-items/wrong-number-generic-args-add.stderr
deleted file mode 100644 (file)
index 6f89441..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0718]: `add` language item must be applied to a trait with 1 generic argument
-  --> $DIR/wrong-number-generic-args-add.rs:11:1
-   |
-LL | #[lang = "add"]
-   | ^^^^^^^^^^^^^^^
-LL | trait MyAdd<'a, T> {}
-   |            ------- this trait has 2 generic arguments, not 1
-
-error[E0369]: cannot add `{integer}` to `{integer}`
-  --> $DIR/wrong-number-generic-args-add.rs:18:7
-   |
-LL |     r + a
-   |     - ^ - {integer}
-   |     |
-   |     {integer}
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0369, E0718.
-For more information about an error, try `rustc --explain E0369`.
diff --git a/src/test/ui/lang-items/wrong-number-generic-args-index.rs b/src/test/ui/lang-items/wrong-number-generic-args-index.rs
deleted file mode 100644 (file)
index 1d90e63..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Checks whether declaring a lang item with the wrong number
-// of generic arguments crashes the compiler (issue #83893).
-
-#![feature(lang_items,no_core)]
-#![no_core]
-#![crate_type="lib"]
-
-#[lang = "sized"]
-trait MySized {}
-
-#[lang = "index"]
-trait MyIndex<'a, T> {}
-//~^^ ERROR: `index` language item must be applied to a trait with 1 generic argument [E0718]
-
-fn ice() {
-    let arr = [0; 5];
-    let _ = arr[2];
-    //~^ ERROR: cannot index into a value of type `[{integer}; 5]` [E0608]
-}
diff --git a/src/test/ui/lang-items/wrong-number-generic-args-index.stderr b/src/test/ui/lang-items/wrong-number-generic-args-index.stderr
deleted file mode 100644 (file)
index bc3f19f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0718]: `index` language item must be applied to a trait with 1 generic argument
-  --> $DIR/wrong-number-generic-args-index.rs:11:1
-   |
-LL | #[lang = "index"]
-   | ^^^^^^^^^^^^^^^^^
-LL | trait MyIndex<'a, T> {}
-   |              ------- this trait has 2 generic arguments, not 1
-
-error[E0608]: cannot index into a value of type `[{integer}; 5]`
-  --> $DIR/wrong-number-generic-args-index.rs:17:13
-   |
-LL |     let _ = arr[2];
-   |             ^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0608, E0718.
-For more information about an error, try `rustc --explain E0608`.
diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.rs
deleted file mode 100644 (file)
index 46ae940..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-pub const fn sof<T>() -> usize {
-    10
-}
-
-fn test<T>() {
-    let _: [u8; sof::<T>()];
-    //~^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr b/src/test/ui/lazy_normalization_consts/feature-gate-lazy_normalization_consts.stderr
deleted file mode 100644 (file)
index 5c167ea..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error: generic parameters may not be used in const operations
-  --> $DIR/feature-gate-lazy_normalization_consts.rs:6:23
-   |
-LL |     let _: [u8; sof::<T>()];
-   |                       ^ cannot perform const operation using `T`
-   |
-   = note: type parameters may not be used in const expressions
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/lazy_normalization_consts/issue-47814.rs b/src/test/ui/lazy_normalization_consts/issue-47814.rs
deleted file mode 100644 (file)
index 1fd0c45..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-#![feature(lazy_normalization_consts)]
-#![allow(incomplete_features)]
-pub struct ArpIPv4<'a> {
-    _s: &'a u8
-}
-
-impl<'a> ArpIPv4<'a> {
-    const LENGTH: usize = 20;
-
-    pub fn to_buffer() -> [u8; Self::LENGTH] {
-        unimplemented!()
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.rs b/src/test/ui/lazy_normalization_consts/issue-57739.rs
deleted file mode 100644 (file)
index 4607f3e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#![feature(lazy_normalization_consts)]
-//~^ WARN the feature `lazy_normalization_consts` is incomplete
-trait ArraySizeTrait {
-    const SIZE: usize = 0;
-}
-
-impl<T: ?Sized> ArraySizeTrait for T {
-    const SIZE: usize = 1;
-}
-
-struct SomeArray<T: ArraySizeTrait> {
-    array: [u8; T::SIZE],
-    //~^ ERROR constant expression depends on a generic parameter
-    phantom: std::marker::PhantomData<T>,
-}
-
-fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/issue-57739.stderr b/src/test/ui/lazy_normalization_consts/issue-57739.stderr
deleted file mode 100644 (file)
index ce0495d..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-57739.rs:1:12
-   |
-LL | #![feature(lazy_normalization_consts)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #72219 <https://github.com/rust-lang/rust/issues/72219> for more information
-
-error: constant expression depends on a generic parameter
-  --> $DIR/issue-57739.rs:12:12
-   |
-LL |     array: [u8; T::SIZE],
-   |            ^^^^^^^^^^^^^
-   |
-   = note: this may fail depending on what value the parameter takes
-
-error: aborting due to previous error; 1 warning emitted
-
diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.rs b/src/test/ui/lazy_normalization_consts/issue-73980.rs
deleted file mode 100644 (file)
index e100406..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// check-pass
-#![feature(lazy_normalization_consts)]
-#![allow(incomplete_features)]
-
-pub struct X<P, Q>(P, Q);
-pub struct L<T: ?Sized>(T);
-
-impl<T: ?Sized> L<T> {
-    const S: usize = 1;
-}
-
-impl<T> X<T, [u8; L::<T>::S]> {}
-//~^ WARN cannot use constants which depend on generic parameters
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/issue-73980.stderr b/src/test/ui/lazy_normalization_consts/issue-73980.stderr
deleted file mode 100644 (file)
index 5ed1ca3..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: cannot use constants which depend on generic parameters in types
-  --> $DIR/issue-73980.rs:12:9
-   |
-LL | impl<T> X<T, [u8; L::<T>::S]> {}
-   |         ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(const_evaluatable_unchecked)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/lazy_normalization_consts/trait-resolution-breakage.rs b/src/test/ui/lazy_normalization_consts/trait-resolution-breakage.rs
deleted file mode 100644 (file)
index df1c99e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-
-trait Trait<T> {
-    const ASSOC_CONST: usize = 0;
-}
-
-impl Trait<()> for u8 {}
-
-// `u8::ASSOC_CONST` is resolved today, but will be ambiguous
-// under lazy normalization.
-fn foo<T, U>() -> [(T, U); u8::ASSOC_CONST]
-where
-    u8: Trait<T> + Trait<U>,
-{
-    todo!()
-}
-
-fn main() {}
diff --git a/src/test/ui/lazy_normalization_consts/unevaluated-consts.rs b/src/test/ui/lazy_normalization_consts/unevaluated-consts.rs
deleted file mode 100644 (file)
index 3f90d22..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// check-pass
-
-// If we allow the parent generics here without using lazy normalization
-// this results in a cycle error.
-struct Foo<T, U>(T, U);
-
-impl<T> From<[u8; 1 + 1]> for Foo<T, [u8; 1 + 1]> {
-    fn from(value: [u8; 1 + 1]) -> Foo<T, [u8; 1 + 1]> {
-        todo!();
-    }
-}
-
-fn break_me<T>()
-where
-    [u8; 1 + 1]: From<[u8; 1 + 1]>
-{}
-
-fn main() {}
index 5a44b8e70655352105a4694d256c60436b169032..3c78dd6c78023398b453f89bb17f20b17323c1a7 100644 (file)
@@ -13,7 +13,7 @@ LL |     legacy_const_generics::foo(0, N + 1, 2);
    |                                   ^ cannot perform const operation using `N`
    |
    = help: const parameters may only be used as standalone arguments, i.e. `N`
-   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+   = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/let-else/let-else-bool-binop-init.fixed b/src/test/ui/let-else/let-else-bool-binop-init.fixed
new file mode 100644 (file)
index 0000000..e47f7f2
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+
+#![feature(let_else)]
+
+fn main() {
+    let true = (true && false) else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else`
+    let true = (true || false) else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else`
+}
diff --git a/src/test/ui/let-else/let-else-bool-binop-init.rs b/src/test/ui/let-else/let-else-bool-binop-init.rs
new file mode 100644 (file)
index 0000000..e443fb0
--- /dev/null
@@ -0,0 +1,8 @@
+// run-rustfix
+
+#![feature(let_else)]
+
+fn main() {
+    let true = true && false else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else`
+    let true = true || false else { return }; //~ ERROR a `||` expression cannot be directly assigned in `let...else`
+}
diff --git a/src/test/ui/let-else/let-else-bool-binop-init.stderr b/src/test/ui/let-else/let-else-bool-binop-init.stderr
new file mode 100644 (file)
index 0000000..6551e24
--- /dev/null
@@ -0,0 +1,24 @@
+error: a `&&` expression cannot be directly assigned in `let...else`
+  --> $DIR/let-else-bool-binop-init.rs:6:16
+   |
+LL |     let true = true && false else { return };
+   |                ^^^^^^^^^^^^^
+   |
+help: wrap the expression in parenthesis
+   |
+LL |     let true = (true && false) else { return };
+   |                +             +
+
+error: a `||` expression cannot be directly assigned in `let...else`
+  --> $DIR/let-else-bool-binop-init.rs:7:16
+   |
+LL |     let true = true || false else { return };
+   |                ^^^^^^^^^^^^^
+   |
+help: wrap the expression in parenthesis
+   |
+LL |     let true = (true || false) else { return };
+   |                +             +
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/let-else/let-else-brace-before-else.fixed b/src/test/ui/let-else/let-else-brace-before-else.fixed
new file mode 100644 (file)
index 0000000..fb4fd77
--- /dev/null
@@ -0,0 +1,26 @@
+// run-rustfix
+
+#![feature(let_else)]
+
+fn main() {
+    let Some(1) = ({ Some(1) }) else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let Some(1) = (loop { break Some(1) }) else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let 2 = 1 + (match 1 { n => n }) else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let Some(1) = (unsafe { unsafe_fn() }) else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+}
+
+unsafe fn unsafe_fn<T>() -> T {
+    unimplemented!();
+}
diff --git a/src/test/ui/let-else/let-else-brace-before-else.rs b/src/test/ui/let-else/let-else-brace-before-else.rs
new file mode 100644 (file)
index 0000000..c4c5a1c
--- /dev/null
@@ -0,0 +1,26 @@
+// run-rustfix
+
+#![feature(let_else)]
+
+fn main() {
+    let Some(1) = { Some(1) } else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let Some(1) = loop { break Some(1) } else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let 2 = 1 + match 1 { n => n } else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+    let Some(1) = unsafe { unsafe_fn() } else {
+        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
+        return;
+    };
+}
+
+unsafe fn unsafe_fn<T>() -> T {
+    unimplemented!();
+}
diff --git a/src/test/ui/let-else/let-else-brace-before-else.stderr b/src/test/ui/let-else/let-else-brace-before-else.stderr
new file mode 100644 (file)
index 0000000..eac029c
--- /dev/null
@@ -0,0 +1,46 @@
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/let-else-brace-before-else.rs:6:29
+   |
+LL |     let Some(1) = { Some(1) } else {
+   |                             ^
+   |
+help: try wrapping the expression in parenthesis
+   |
+LL |     let Some(1) = ({ Some(1) }) else {
+   |                   +           +
+
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/let-else-brace-before-else.rs:10:40
+   |
+LL |     let Some(1) = loop { break Some(1) } else {
+   |                                        ^
+   |
+help: try wrapping the expression in parenthesis
+   |
+LL |     let Some(1) = (loop { break Some(1) }) else {
+   |                   +                      +
+
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/let-else-brace-before-else.rs:14:34
+   |
+LL |     let 2 = 1 + match 1 { n => n } else {
+   |                                  ^
+   |
+help: try wrapping the expression in parenthesis
+   |
+LL |     let 2 = 1 + (match 1 { n => n }) else {
+   |                 +                  +
+
+error: right curly brace `}` before `else` in a `let...else` statement not allowed
+  --> $DIR/let-else-brace-before-else.rs:18:40
+   |
+LL |     let Some(1) = unsafe { unsafe_fn() } else {
+   |                                        ^
+   |
+help: try wrapping the expression in parenthesis
+   |
+LL |     let Some(1) = (unsafe { unsafe_fn() }) else {
+   |                   +                      +
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/let-else/let-else-check.rs b/src/test/ui/let-else/let-else-check.rs
new file mode 100644 (file)
index 0000000..ab76344
--- /dev/null
@@ -0,0 +1,14 @@
+#![feature(let_else)]
+
+#![deny(unused_variables)]
+
+fn main() {
+    // type annotation, attributes
+    #[allow(unused_variables)]
+    let Some(_): Option<u32> = Some(Default::default()) else {
+        let x = 1; // OK
+        return;
+    };
+
+    let x = 1; //~ ERROR unused variable: `x`
+}
diff --git a/src/test/ui/let-else/let-else-check.stderr b/src/test/ui/let-else/let-else-check.stderr
new file mode 100644 (file)
index 0000000..50e54d3
--- /dev/null
@@ -0,0 +1,14 @@
+error: unused variable: `x`
+  --> $DIR/let-else-check.rs:13:9
+   |
+LL |     let x = 1;
+   |         ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+note: the lint level is defined here
+  --> $DIR/let-else-check.rs:3:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/let-else/let-else-irrefutable.rs b/src/test/ui/let-else/let-else-irrefutable.rs
new file mode 100644 (file)
index 0000000..b1e09a1
--- /dev/null
@@ -0,0 +1,7 @@
+// check-pass
+
+#![feature(let_else)]
+
+fn main() {
+    let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern
+}
diff --git a/src/test/ui/let-else/let-else-irrefutable.stderr b/src/test/ui/let-else/let-else-irrefutable.stderr
new file mode 100644 (file)
index 0000000..e030c50
--- /dev/null
@@ -0,0 +1,12 @@
+warning: irrefutable `let...else` pattern
+  --> $DIR/let-else-irrefutable.rs:6:5
+   |
+LL |     let x = 1 else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(irrefutable_let_patterns)]` on by default
+   = note: this pattern will always match, so the `else` clause is useless
+   = help: consider removing the `else` clause
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/let-else/let-else-missing-semicolon.rs b/src/test/ui/let-else/let-else-missing-semicolon.rs
new file mode 100644 (file)
index 0000000..ed9d79f
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(let_else)]
+
+fn main() {
+    let Some(x) = Some(1) else {
+        return;
+    } //~ ERROR expected `;`, found keyword `let`
+    let _ = "";
+    let Some(x) = Some(1) else {
+        panic!();
+    } //~ ERROR expected `;`, found `}`
+}
diff --git a/src/test/ui/let-else/let-else-missing-semicolon.stderr b/src/test/ui/let-else/let-else-missing-semicolon.stderr
new file mode 100644 (file)
index 0000000..1818a0b
--- /dev/null
@@ -0,0 +1,18 @@
+error: expected `;`, found keyword `let`
+  --> $DIR/let-else-missing-semicolon.rs:6:6
+   |
+LL |     }
+   |      ^ help: add `;` here
+LL |     let _ = "";
+   |     --- unexpected token
+
+error: expected `;`, found `}`
+  --> $DIR/let-else-missing-semicolon.rs:10:6
+   |
+LL |     }
+   |      ^ help: add `;` here
+LL | }
+   | - unexpected token
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/let-else/let-else-non-diverging.rs b/src/test/ui/let-else/let-else-non-diverging.rs
new file mode 100644 (file)
index 0000000..a1cee33
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(let_else)]
+
+fn main() {
+    let Some(x) = Some(1) else { //~ ERROR does not diverge
+        Some(2)
+    };
+    let Some(x) = Some(1) else { //~ ERROR does not diverge
+        if 1 == 1 {
+            panic!();
+        }
+    };
+    let Some(x) = Some(1) else { Some(2) }; //~ ERROR does not diverge
+}
diff --git a/src/test/ui/let-else/let-else-non-diverging.stderr b/src/test/ui/let-else/let-else-non-diverging.stderr
new file mode 100644 (file)
index 0000000..fd5a18c
--- /dev/null
@@ -0,0 +1,44 @@
+error[E0308]: `else` clause of `let...else` does not diverge
+  --> $DIR/let-else-non-diverging.rs:12:32
+   |
+LL |     let Some(x) = Some(1) else { Some(2) };
+   |                                ^^^^^^^^^^^ expected `!`, found enum `Option`
+   |
+   = note: expected type `!`
+              found type `Option<{integer}>`
+   = help: try adding a diverging expression, such as `return` or `panic!(..)`
+   = help: ...or use `match` instead of `let...else`
+
+error[E0308]: `else` clause of `let...else` does not diverge
+  --> $DIR/let-else-non-diverging.rs:7:32
+   |
+LL |       let Some(x) = Some(1) else {
+   |  ________________________________^
+LL | |         if 1 == 1 {
+LL | |             panic!();
+LL | |         }
+LL | |     };
+   | |_____^ expected `!`, found `()`
+   |
+   = note: expected type `!`
+              found type `()`
+   = help: try adding a diverging expression, such as `return` or `panic!(..)`
+   = help: ...or use `match` instead of `let...else`
+
+error[E0308]: `else` clause of `let...else` does not diverge
+  --> $DIR/let-else-non-diverging.rs:4:32
+   |
+LL |       let Some(x) = Some(1) else {
+   |  ________________________________^
+LL | |         Some(2)
+LL | |     };
+   | |_____^ expected `!`, found enum `Option`
+   |
+   = note: expected type `!`
+              found type `Option<{integer}>`
+   = help: try adding a diverging expression, such as `return` or `panic!(..)`
+   = help: ...or use `match` instead of `let...else`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/let-else/let-else-run-pass.rs b/src/test/ui/let-else/let-else-run-pass.rs
new file mode 100644 (file)
index 0000000..5d96623
--- /dev/null
@@ -0,0 +1,35 @@
+// run-pass
+
+#![feature(let_else)]
+
+fn main() {
+    #[allow(dead_code)]
+    enum MyEnum {
+        A(String),
+        B { f: String },
+        C,
+    }
+    // ref binding to non-copy value and or-pattern
+    let (MyEnum::A(ref x) | MyEnum::B { f: ref x }) = (MyEnum::B { f: String::new() }) else {
+        panic!();
+    };
+    assert_eq!(x, "");
+
+    // nested let-else
+    let mut x = 1;
+    loop {
+        let 4 = x else {
+            let 3 = x else {
+                x += 1;
+                continue;
+            };
+            break;
+        };
+        panic!();
+    }
+    assert_eq!(x, 3);
+
+    // else return
+    let Some(1) = Some(2) else { return };
+    panic!();
+}
diff --git a/src/test/ui/let-else/let-else-scope.rs b/src/test/ui/let-else/let-else-scope.rs
new file mode 100644 (file)
index 0000000..f17682d
--- /dev/null
@@ -0,0 +1,7 @@
+#![feature(let_else)]
+
+fn main() {
+    let Some(x) = Some(2) else {
+        panic!("{}", x); //~ ERROR cannot find value `x` in this scope
+    };
+}
diff --git a/src/test/ui/let-else/let-else-scope.stderr b/src/test/ui/let-else/let-else-scope.stderr
new file mode 100644 (file)
index 0000000..4b3936e
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/let-else-scope.rs:5:22
+   |
+LL |         panic!("{}", x);
+   |                      ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
index a0a96d01be3f59389e6d1c0fd824206367060a4e..7d762b05c97b998974937afa21dec72eb4af55cf 100644 (file)
@@ -5,7 +5,7 @@
 //
 //[warn_deny] compile-flags: --warn missing_abi --deny missing_abi
 //[forbid_warn] compile-flags: --warn missing_abi --forbid missing_abi
-//[force_warn_deny] compile-flags: -Z unstable-options --force-warn missing_abi --allow missing_abi
+//[force_warn_deny] compile-flags: --force-warn missing_abi --allow missing_abi
 //[force_warn_deny] check-pass
 
 
index 55544cc73781a6dd86700b8dccfd2bc71cae4d9a..f3dea87a6b69a1fccc2a66f9d000c3013d40aca4 100644 (file)
@@ -1,7 +1,7 @@
 // Checks that rustc correctly errors when passed an invalid lint with
 // `--force-warn`. This is a regression test for issue #86958.
 //
-// compile-flags: -Z unstable-options --force-warn foo-qux
+// compile-flags: --force-warn foo-qux
 // error-pattern: unknown lint: `foo_qux`
 
 fn main() {}
index 4367c3b4500d5fe1f471d745436f822ec08bc6e8..9ce9f405aee699d38d5ca0b1b30e0f5ce90651f2 100644 (file)
@@ -6,10 +6,6 @@ error[E0602]: unknown lint: `foo_qux`
    |
    = note: requested on the command line with `--force-warn foo_qux`
 
-error[E0602]: unknown lint: `foo_qux`
-   |
-   = note: requested on the command line with `--force-warn foo_qux`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0602`.
index 6ee5ba6793280676f7bb885c4dd11c63edc6a18a..adcefc7ec78c4190d723423f4e67ecffc7ea1749 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite allowing all warnings in module
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 #![allow(warnings)]
index fd0b886d84dbeef48ed775d6248839277d58f8e5..b24ab822d93037b4f61a4bc6a32f0fff5445cd24 100644 (file)
@@ -1,5 +1,5 @@
 // --force-warn $LINT causes $LINT (which is allow-by-default) to warn
-// compile-flags: --force-warn elided_lifetimes_in_paths -Zunstable-options
+// compile-flags: --force-warn elided_lifetimes_in_paths
 // check-pass
 
 struct Foo<'a> {
index 82a584ac97265e7421716fc9252f89be11df9454..08e75a775d0b55b98a343610efbb0b18d75c30ec 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn const_err -Zunstable-options
+// compile-flags: --force-warn const_err
 // check-pass
 
 #![allow(const_err)]
index 86ab12668a3e4f0dd98d4520185f94117a3ed4c7..9b1edba41aafeec4ab481508287271efab2bdd22 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite $LINT_GROUP (which contains $LINT) being allowed
-// compile-flags: --force-warn bare_trait_objects -Zunstable-options
+// compile-flags: --force-warn bare_trait_objects
 // check-pass
 
 #![allow(rust_2018_idioms)]
index 7204782a324e301faf1085ac21f9aa98316d803f..4ac29ff7d99b7e57272ebe02fed7674d0d8e1141 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
 // check-pass
 
 #![allow(dead_code)]
index de3a1bd8dd71996e3de895a3c34ef30b67d2adab..9609ea994312fb8fb0cff619094584ba09441882 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT casuses $LINT to warn despite --cap-lints
 // set to allow
-// compile-flags: --cap-lints allow  --force-warn bare_trait_objects -Zunstable-options
+// compile-flags: --cap-lints allow  --force-warn bare_trait_objects
 // check-pass
 
 pub trait SomeTrait {}
index 70fb90dc1992b9897711c4844233072ea2dd2d14..e65f156bfdc9a8c69b9460d159ef62079e12728f 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT to warn despite $LINT being
 // allowed in module and cap-lints set to warn
-// compile-flags: --cap-lints warn  --force-warn rust-2021-compatibility -Zunstable-options
+// compile-flags: --cap-lints warn  --force-warn rust-2021-compatibility
 // check-pass
 #![allow(ellipsis_inclusive_range_patterns)]
 
index b0a15cc2fba063179e9f02ecb0a68df181e6159e..e371029032fe906be94f93a95ee88634a13003c9 100644 (file)
@@ -1,5 +1,5 @@
 // --force-warn $LINT causes $LINT (which is deny-by-default) to warn
-// compile-flags: --force-warn const_err -Zunstable-options
+// compile-flags: --force-warn const_err
 // check-pass
 
 const C: i32 = 1 / 0;
index e5dcd9a7ea16f66a5bb521760b6b80b145d8be4b..4b95f4d2dfbbaa5b9fe5fc42263bfe3c1f66ca1b 100644 (file)
@@ -1,7 +1,7 @@
 // --force-warn $LINT_GROUP causes $LINT in $LINT_GROUP to warn
 // despite all warnings being allowed in module
 // warn-by-default lint to warn
-// compile-flags: --force-warn nonstandard_style -Zunstable-options
+// compile-flags: --force-warn nonstandard_style
 // check-pass
 
 #![allow(warnings)]
index dc13b2b24748cae831aa753d28a5301de55601a1..99cad614c25cd38acab5ba2fc752afede288e215 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT to warn despite
 // $LINT_GROUP being allowed in module
-// compile-flags: --force-warn rust_2018_idioms -Zunstable-options
+// compile-flags: --force-warn rust_2018_idioms
 // check-pass
 
 #![allow(rust_2018_idioms)]
index b7f79b3d4aa3bf9171e8a50eeeeb1c8e2a17d787..f0aacd773401f6cf433700995ae6dac24fb99b2a 100644 (file)
@@ -1,6 +1,6 @@
 // --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn
 // despite $LINT being allowed in module
-// compile-flags: --force-warn rust-2018-idioms -Zunstable-options
+// compile-flags: --force-warn rust-2018-idioms
 // check-pass
 
 #![allow(bare_trait_objects)]
index 05d7d924c8fabe0aa762309665c09358d27db06f..c66037e9a73ae6d01acbe5e466208575ff956df7 100644 (file)
@@ -21,8 +21,6 @@ fn forbid_first(num: i32) -> i32 {
     #![deny(unused)]
     //~^ ERROR: deny(unused) incompatible with previous forbid
     //~| WARNING being phased out
-    //~| ERROR: deny(unused) incompatible with previous forbid
-    //~| WARNING being phased out
     #![warn(unused)]
     #![allow(unused)]
 
index 475410cecffa30b105a618f9924fa93ef502bb62..5093715decfc1925e96768f19644de41d785fe20 100644 (file)
@@ -14,16 +14,5 @@ LL | #![forbid(forbidden_lint_groups)]
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
-error: deny(unused) incompatible with previous forbid
-  --> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:21:13
-   |
-LL |     #![forbid(unused)]
-   |               ------ `forbid` level set here
-LL |     #![deny(unused)]
-   |             ^^^^^^ overruled by previous forbid
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/lint/lint-level-macro-def-mod.rs b/src/test/ui/lint/lint-level-macro-def-mod.rs
new file mode 100644 (file)
index 0000000..79f7d12
--- /dev/null
@@ -0,0 +1,17 @@
+// This checks that exported macros lint as part of their module of origin, not
+// the root module.
+//
+// check-pass
+
+//! Top level documentation
+#![deny(missing_docs)]
+
+#[allow(missing_docs)]
+mod module {
+    #[macro_export]
+    macro_rules! hello {
+        () => ()
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-level-macro-def.rs b/src/test/ui/lint/lint-level-macro-def.rs
new file mode 100644 (file)
index 0000000..720f4b4
--- /dev/null
@@ -0,0 +1,17 @@
+// Checks that you can set a lint level specficially for a macro definition.
+//
+// This is a regression test for issue #59306.
+//
+// check-pass
+
+
+#[deny(missing_docs)]
+mod module {
+    #[allow(missing_docs)]
+    #[macro_export]
+    macro_rules! hello {
+        () => ()
+    }
+}
+
+fn main() {}
index 8d1d5c568803b8ad3d3310c7b1b520dfb0965618..0d4332ed08b26955b0eb119561c344e709ee2a3c 100644 (file)
@@ -29,13 +29,13 @@ macro_rules! old_style_mod_private_macro {
 
     #[macro_export]
     macro_rules! exported_to_top_level {
-        //~^ ERROR missing documentation for macro
+        //~^ ERROR missing documentation for macro
         () => ()
     }
 }
 
 pub macro top_level_pub_macro {
-    //~^ ERROR missing documentation for macro
+    //~^ ERROR missing documentation for macro
     () => ()
 }
 
index a5d39faf40562ceef142a03a9d104830d388c26f..979b007d0ecd69c1c08f89c5d45f9feefbb49124 100644 (file)
@@ -1,4 +1,4 @@
-error: missing documentation for macro
+error: missing documentation for macro
   --> $DIR/missing-doc-private-macro.rs:31:5
    |
 LL |     macro_rules! exported_to_top_level {
@@ -10,7 +10,7 @@ note: the lint level is defined here
 LL | #![deny(missing_docs)]
    |         ^^^^^^^^^^^^
 
-error: missing documentation for macro
+error: missing documentation for macro
   --> $DIR/missing-doc-private-macro.rs:37:1
    |
 LL | pub macro top_level_pub_macro {
index 486ec3c46804fb0f0d01f760baa7c4c4b5cdfaa7..ba330258d111fff04c092114e60f2c60dde5c321 100644 (file)
 #![forbid(unused, non_snake_case)]
 #![forbid(forbidden_lint_groups)]
 
-#[allow(unused_variables)] //~ ERROR incompatible with previous
+#[allow(unused_variables)]
 //~^ ERROR incompatible with previous
 //~| WARNING this was previously accepted by the compiler
-//~| WARNING this was previously accepted by the compiler
 fn foo() {}
 
 #[allow(unused)] //~ ERROR incompatible with previous
index d69157a8bb3adc9d316d331c3810bc4348702c26..7814573210548e291b541a967bd2097625438b21 100644 (file)
@@ -16,7 +16,7 @@ LL | #![forbid(forbidden_lint_groups)]
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
 error: allow(unused) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:26:9
+  --> $DIR/outer-forbid.rs:25:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |           ------ `forbid` level set here
@@ -28,7 +28,7 @@ LL | #[allow(unused)]
    = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
 
 error[E0453]: allow(nonstandard_style) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:30:9
+  --> $DIR/outer-forbid.rs:29:9
    |
 LL | #![forbid(unused, non_snake_case)]
    |                   -------------- `forbid` level set here
@@ -36,18 +36,6 @@ LL | #![forbid(unused, non_snake_case)]
 LL | #[allow(nonstandard_style)]
    |         ^^^^^^^^^^^^^^^^^ overruled by previous forbid
 
-error: allow(unused_variables) incompatible with previous forbid
-  --> $DIR/outer-forbid.rs:20:9
-   |
-LL | #![forbid(unused, non_snake_case)]
-   |           ------ `forbid` level set here
-...
-LL | #[allow(unused_variables)]
-   |         ^^^^^^^^^^^^^^^^ overruled by previous forbid
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0453`.
diff --git a/src/test/ui/lint/unused/issue-88519-unused-paren.rs b/src/test/ui/lint/unused/issue-88519-unused-paren.rs
new file mode 100644 (file)
index 0000000..be02fcd
--- /dev/null
@@ -0,0 +1,94 @@
+// check-pass
+// Make sure unused parens lint doesn't emit a false positive.
+// See https://github.com/rust-lang/rust/issues/88519
+#![deny(unused_parens)]
+#![feature(type_ascription)]
+
+// binary ops are tested in issue-71290-unused-paren-binop.rs
+
+mod call {
+    fn noop() -> u8 { 0 }
+    fn outside() -> u8 {
+        ({ noop })()
+    }
+    fn inside() -> u8 {
+        ({ noop }())
+    }
+    fn outside_match() -> u8 {
+        (match noop { x => x })()
+    }
+    fn inside_match() -> u8 {
+        (match noop { x => x }())
+    }
+    fn outside_if() -> u8 {
+        (if false { noop } else { noop })()
+    }
+    fn inside_if() -> u8 {
+        (if false { noop } else { noop }())
+    }
+}
+
+mod casts {
+    fn outside() -> u8 {
+        ({ 0 }) as u8
+    }
+    fn inside() -> u8 {
+        ({ 0 } as u8)
+    }
+    fn outside_match() -> u8 {
+        (match 0 { x => x }) as u8
+    }
+    fn inside_match() -> u8 {
+        (match 0 { x => x } as u8)
+    }
+    fn outside_if() -> u8 {
+        (if false { 0 } else { 0 }) as u8
+    }
+    fn inside_if() -> u8 {
+        (if false { 0 } else { 0 } as u8)
+    }
+}
+
+mod typeascription {
+    fn outside() -> u8 {
+        ({ 0 }): u8
+    }
+    fn inside() -> u8 {
+        ({ 0 }: u8)
+    }
+    fn outside_match() -> u8 {
+        (match 0 { x => x }): u8
+    }
+    fn inside_match() -> u8 {
+        (match 0 { x => x }: u8)
+    }
+    fn outside_if() -> u8 {
+        (if false { 0 } else { 0 }): u8
+    }
+    fn inside_if() -> u8 {
+        (if false { 0 } else { 0 }: u8)
+    }
+}
+
+mod index {
+    fn outside(x: &[u8]) -> u8 {
+        ({ x })[0]
+    }
+    fn inside(x: &[u8]) -> u8 {
+        ({ x }[0])
+    }
+    fn outside_match(x: &[u8]) -> u8 {
+        (match x { x => x })[0]
+    }
+    fn inside_match(x: &[u8]) -> u8 {
+        (match x { x => x }[0])
+    }
+    fn outside_if(x: &[u8]) -> u8 {
+        (if false { x } else { x })[0]
+    }
+    fn inside_if(x: &[u8]) -> u8 {
+        (if false { x } else { x }[0])
+    }
+}
+
+fn main() {}
index d08fbac0bcaabc006112c6dafc5f7b0b79710ea2..d9dac5de6226c304f9c044686fb98ccabfddec5c 100644 (file)
@@ -1,17 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/liveness-return-last-stmt-semi.rs:4:41
-   |
-LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
-   |                                ---      ^^^    - help: consider removing this semicolon
-   |                                |        |
-   |                                |        expected `i32`, found `()`
-   |                                implicitly returns `()` as its body has no tail or `return` expression
-...
-LL |     test!();
-   |     -------- in this macro invocation
-   |
-   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0308]: mismatched types
   --> $DIR/liveness-return-last-stmt-semi.rs:7:19
    |
@@ -38,6 +24,20 @@ LL | fn baz(x: u64) -> u32 {
    |    |
    |    implicitly returns `()` as its body has no tail or `return` expression
 
+error[E0308]: mismatched types
+  --> $DIR/liveness-return-last-stmt-semi.rs:4:41
+   |
+LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
+   |                                ---      ^^^    - help: consider removing this semicolon
+   |                                |        |
+   |                                |        expected `i32`, found `()`
+   |                                implicitly returns `()` as its body has no tail or `return` expression
+...
+LL |     test!();
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
index 98ea4d71ccf4f0189903ca5ad85b6a579255ae88..d446d57d3964726aac90d4d741011f2b4896d40d 100644 (file)
@@ -1,5 +1,6 @@
 // edition:2018
 // check-pass
+#![feature(generators)]
 #![warn(unused)]
 #![allow(unreachable_code)]
 
@@ -105,4 +106,39 @@ pub fn h<T: Copy + Default + std::fmt::Debug>() {
     };
 }
 
+async fn yield_now() {
+    todo!();
+}
+
+pub fn async_generator() {
+    let mut state: u32 = 0;
+
+    let _ = async {
+        state = 1;
+        yield_now().await;
+        state = 2;
+        yield_now().await;
+        state = 3;
+    };
+
+    let _ = async move {
+        state = 4;  //~  WARN value assigned to `state` is never read
+                    //~| WARN unused variable: `state`
+        yield_now().await;
+        state = 5;  //~ WARN value assigned to `state` is never read
+    };
+}
+
+pub fn generator() {
+    let mut s: u32 = 0;
+    let _ = |_| {
+        s = 0;
+        yield ();
+        s = 1; //~ WARN value assigned to `s` is never read
+        yield (s = 2);
+        s = yield (); //~ WARN value assigned to `s` is never read
+        s = 3;
+    };
+}
+
 fn main() {}
index 14fed917864361d0810912e8704066fca84fbcbc..d1723302513652fafe204bef5fe72fb3f4588832 100644 (file)
@@ -1,11 +1,11 @@
 warning: value assigned to `last` is never read
-  --> $DIR/liveness-upvars.rs:9:9
+  --> $DIR/liveness-upvars.rs:10:9
    |
 LL |         last = Some(s);
    |         ^^^^
    |
 note: the lint level is defined here
-  --> $DIR/liveness-upvars.rs:3:9
+  --> $DIR/liveness-upvars.rs:4:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
@@ -13,13 +13,13 @@ LL | #![warn(unused)]
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `last`
-  --> $DIR/liveness-upvars.rs:9:9
+  --> $DIR/liveness-upvars.rs:10:9
    |
 LL |         last = Some(s);
    |         ^^^^
    |
 note: the lint level is defined here
-  --> $DIR/liveness-upvars.rs:3:9
+  --> $DIR/liveness-upvars.rs:4:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
@@ -27,7 +27,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `sum`
-  --> $DIR/liveness-upvars.rs:21:9
+  --> $DIR/liveness-upvars.rs:22:9
    |
 LL |         sum += x;
    |         ^^^
@@ -35,7 +35,7 @@ LL |         sum += x;
    = help: did you mean to capture by reference instead?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:31:9
+  --> $DIR/liveness-upvars.rs:32:9
    |
 LL |         c = 1;
    |         ^
@@ -43,7 +43,7 @@ LL |         c = 1;
    = help: did you mean to capture by reference instead?
 
 warning: value captured by `c` is never read
-  --> $DIR/liveness-upvars.rs:35:9
+  --> $DIR/liveness-upvars.rs:36:9
    |
 LL |         c = 1;
    |         ^
@@ -51,7 +51,7 @@ LL |         c = 1;
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `c`
-  --> $DIR/liveness-upvars.rs:41:9
+  --> $DIR/liveness-upvars.rs:42:9
    |
 LL |         c += 1;
    |         ^
@@ -59,7 +59,7 @@ LL |         c += 1;
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:44:9
+  --> $DIR/liveness-upvars.rs:45:9
    |
 LL |         c += 1;
    |         ^
@@ -67,7 +67,7 @@ LL |         c += 1;
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `c`
-  --> $DIR/liveness-upvars.rs:44:9
+  --> $DIR/liveness-upvars.rs:45:9
    |
 LL |         c += 1;
    |         ^
@@ -75,7 +75,7 @@ LL |         c += 1;
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:57:9
+  --> $DIR/liveness-upvars.rs:58:9
    |
 LL |         c += 1;
    |         ^
@@ -83,7 +83,7 @@ LL |         c += 1;
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `c` is never read
-  --> $DIR/liveness-upvars.rs:63:9
+  --> $DIR/liveness-upvars.rs:64:9
    |
 LL |         c += 1;
    |         ^
@@ -91,7 +91,7 @@ LL |         c += 1;
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `d` is never read
-  --> $DIR/liveness-upvars.rs:72:13
+  --> $DIR/liveness-upvars.rs:73:13
    |
 LL |             d = Some("d1");
    |             ^
@@ -99,7 +99,7 @@ LL |             d = Some("d1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `e` is never read
-  --> $DIR/liveness-upvars.rs:76:13
+  --> $DIR/liveness-upvars.rs:77:13
    |
 LL |             e = Some("e1");
    |             ^
@@ -107,7 +107,7 @@ LL |             e = Some("e1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `e` is never read
-  --> $DIR/liveness-upvars.rs:78:13
+  --> $DIR/liveness-upvars.rs:79:13
    |
 LL |             e = Some("e2");
    |             ^
@@ -115,7 +115,7 @@ LL |             e = Some("e2");
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `e`
-  --> $DIR/liveness-upvars.rs:76:13
+  --> $DIR/liveness-upvars.rs:77:13
    |
 LL |             e = Some("e1");
    |             ^
@@ -123,7 +123,7 @@ LL |             e = Some("e1");
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `v` is never read
-  --> $DIR/liveness-upvars.rs:86:13
+  --> $DIR/liveness-upvars.rs:87:13
    |
 LL |             v = T::default();
    |             ^
@@ -131,7 +131,7 @@ LL |             v = T::default();
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `z` is never read
-  --> $DIR/liveness-upvars.rs:98:17
+  --> $DIR/liveness-upvars.rs:99:17
    |
 LL |                 z = T::default();
    |                 ^
@@ -139,12 +139,52 @@ LL |                 z = T::default();
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `z`
-  --> $DIR/liveness-upvars.rs:98:17
+  --> $DIR/liveness-upvars.rs:99:17
    |
 LL |                 z = T::default();
    |                 ^
    |
    = help: did you mean to capture by reference instead?
 
-warning: 17 warnings emitted
+warning: value assigned to `state` is never read
+  --> $DIR/liveness-upvars.rs:125:9
+   |
+LL |         state = 4;
+   |         ^^^^^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `state` is never read
+  --> $DIR/liveness-upvars.rs:128:9
+   |
+LL |         state = 5;
+   |         ^^^^^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `state`
+  --> $DIR/liveness-upvars.rs:125:9
+   |
+LL |         state = 4;
+   |         ^^^^^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value assigned to `s` is never read
+  --> $DIR/liveness-upvars.rs:137:9
+   |
+LL |         s = 1;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `s` is never read
+  --> $DIR/liveness-upvars.rs:139:9
+   |
+LL |         s = yield ();
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: 22 warnings emitted
 
diff --git a/src/test/ui/macros/issue-87877.rs b/src/test/ui/macros/issue-87877.rs
new file mode 100644 (file)
index 0000000..a40e2c5
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+macro_rules! two_items {
+    () => {
+        extern "C" {}
+        extern "C" {}
+    };
+}
+
+macro_rules! single_expr_funneler {
+    ($expr:expr) => {
+        $expr; // note the semicolon, it changes the statement kind during parsing
+    };
+}
+
+macro_rules! single_item_funneler {
+    ($item:item) => {
+        $item
+    };
+}
+
+fn main() {
+    single_expr_funneler! { two_items! {} }
+    single_item_funneler! { two_items! {} }
+}
index a5f538ba6b36acae48dcc2598a99d04b059214b0..2d02b95288df45e7fc0b8121de4ce838de3e2f41 100644 (file)
@@ -1,7 +1,8 @@
 // run-pass
 // aux-build:unstable-macros.rs
 
-#![feature(unstable_macros, local_unstable)]
+#![unstable(feature = "one_two_three_testing", issue = "none")]
+#![feature(staged_api, unstable_macros, local_unstable)]
 
 #[macro_use] extern crate unstable_macros;
 
index e34164ec0db249af65a512112f76cdbe65564107..c994ee4f6d4ffe39b4246a51a77f2fd8ee8b63cb 100644 (file)
@@ -1,11 +1,11 @@
 error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
-  --> $DIR/match-pattern-field-mismatch.rs:10:11
+  --> $DIR/match-pattern-field-mismatch.rs:10:22
    |
 LL |         Rgb(usize, usize, usize),
-   |         ------------------------ tuple variant defined here
+   |             -----  -----  ----- tuple variant has 3 fields
 ...
 LL |           Color::Rgb(_, _) => { }
-   |           ^^^^^^^^^^^^^^^^ expected 3 fields, found 2
+   |                      ^  ^ expected 3 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/mir/issue-75053.in_bindings.stderr b/src/test/ui/mir/issue-75053.in_bindings.stderr
deleted file mode 100644 (file)
index d75996b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0557]: feature has been removed
-  --> $DIR/issue-75053.rs:7:34
-   |
-LL | #![cfg_attr(in_bindings, feature(impl_trait_in_bindings))]
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^ feature has been removed
-   |
-   = note: removed due to being incomplete and unstable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0557`.
diff --git a/src/test/ui/mir/issue-80742.rs b/src/test/ui/mir/issue-80742.rs
deleted file mode 100644 (file)
index c06d182..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// check-fail
-
-// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place
-
-#![allow(incomplete_features)]
-#![feature(const_evaluatable_checked)]
-#![feature(const_generics)]
-
-use std::fmt::Debug;
-use std::marker::PhantomData;
-use std::mem::size_of;
-
-struct Inline<T>
-where
-    [u8; size_of::<T>() + 1]: ,
-{
-    _phantom: PhantomData<T>,
-    buf: [u8; size_of::<T>() + 1],
-}
-
-impl<T> Inline<T>
-where
-    [u8; size_of::<T>() + 1]: ,
-{
-    pub fn new(val: T) -> Inline<T> {
-        todo!()
-    }
-}
-
-fn main() {
-    let dst = Inline::<dyn Debug>::new(0); //~ ERROR
-    //~^ ERROR
-}
diff --git a/src/test/ui/mir/issue-80742.stderr b/src/test/ui/mir/issue-80742.stderr
deleted file mode 100644 (file)
index b2b40be..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
-  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-  ::: $DIR/issue-80742.rs:23:10
-   |
-LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:23:10
-
-error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied
-  --> $DIR/issue-80742.rs:31:36
-   |
-LL | / struct Inline<T>
-LL | | where
-LL | |     [u8; size_of::<T>() + 1]: ,
-LL | | {
-LL | |     _phantom: PhantomData<T>,
-LL | |     buf: [u8; size_of::<T>() + 1],
-LL | | }
-   | |_- function or associated item `new` not found for this
-...
-LL |       let dst = Inline::<dyn Debug>::new(0);
-   |                                      ^^^ function or associated item cannot be called on `Inline<dyn Debug>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-   |
-LL |   pub trait Debug {
-   |   --------------- doesn't satisfy `dyn Debug: Sized`
-   |
-   = note: the following trait bounds were not satisfied:
-           `dyn Debug: Sized`
-
-error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
-  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-   |
-  ::: $DIR/issue-80742.rs:15:10
-   |
-LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:15:10
-
-error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
-  --> $DIR/issue-80742.rs:31:15
-   |
-LL |     let dst = Inline::<dyn Debug>::new(0);
-   |               ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Debug`
-note: required by a bound in `Inline`
-  --> $DIR/issue-80742.rs:13:15
-   |
-LL | struct Inline<T>
-   |               ^ required by this bound in `Inline`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | struct Inline<T: ?Sized>
-   |                ++++++++
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0080, E0277, E0599.
-For more information about an error, try `rustc --explain E0080`.
index a64cb82305a4825dce162574216ae23a708495df..9867addaf38e7ac23d1e62507b107481078be061 100644 (file)
@@ -2,10 +2,10 @@ error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/issue-75361-mismatched-impl.rs:18:3
    |
 LL |   fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType>>;
-   |   --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait<Item = &_> + 'static)>`
+   |   --------------------------------------------------------------------- expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>`
 ...
 LL |   fn adjacent_edges(&self) -> Box<dyn MyTrait<Item = &Self::EdgeType> + '_> {
-   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box<dyn MyTrait<Item = &_>>`
+   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> Box<dyn MyTrait<Item = &T>>`
    |
    = note: expected `fn(&T) -> Box<(dyn MyTrait<Item = &T> + 'static)>`
               found `fn(&T) -> Box<dyn MyTrait<Item = &T>>`
index 0cd8e956d309f40e4642567265830900de9b936a..978eeb868edc00bee3722edf62330d0cc720c0d3 100644 (file)
@@ -10,8 +10,8 @@ fn main() {
     let f = &mut e;
     let g = f;
     match e {
-        Xyz::A => println!("a"),
         //~^ cannot use `e` because it was mutably borrowed [E0503]
+        Xyz::A => println!("a"),
         Xyz::B => println!("b"),
     };
     *g = Xyz::B;
index 1607304e6716b541d03abdcf158adc706dd939d1..9d4682667dddddbfcf9032509fab39eed1badccf 100644 (file)
@@ -1,11 +1,11 @@
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowed-match-issue-45045.rs:13:9
+  --> $DIR/borrowed-match-issue-45045.rs:12:11
    |
 LL |     let f = &mut e;
    |             ------ borrow of `e` occurs here
-...
-LL |         Xyz::A => println!("a"),
-   |         ^^^^^^ use of borrowed `e`
+LL |     let g = f;
+LL |     match e {
+   |           ^ use of borrowed `e`
 ...
 LL |     *g = Xyz::B;
    |     ----------- borrow later used here
index 87162904ba6cd9c171756563d40a916ccf4dfa6a..ad928f1bbc984373031b9be3ebaec01b64d027d3 100644 (file)
@@ -26,7 +26,7 @@ LL |     let y = &x;
 LL |     x = 0;
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL |     move || *y;
-   |              - borrow later captured here by closure
+   |             -- borrow later captured here by closure
 
 error: aborting due to 3 previous errors
 
index 450993425e26b99fe8cf9cc11d423745941d74b6..18696f57c44aef80ac01115c80833feece008a1c 100644 (file)
@@ -13,11 +13,19 @@ LL |         (&mut self).bar();
 error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-51191.rs:7:9
    |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/issue-51191.rs:4:18
+   |
+LL |     fn bar(self: &mut Self) {
+   |                  ^^^^^^^^^
+help: try removing `&mut` here
+  --> $DIR/issue-51191.rs:7:9
+   |
 LL |         (&mut self).bar();
    |         ^^^^^^^^^^^
-   |         |
-   |         cannot borrow as mutable
-   |         help: try removing `&mut` here
 
 error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-51191.rs:13:9
@@ -42,11 +50,19 @@ LL |         (&mut self).bar();
 error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
   --> $DIR/issue-51191.rs:28:9
    |
+LL |         (&mut self).bar();
+   |         ^^^^^^^^^^^ cannot borrow as mutable
+   |
+note: the binding is already a mutable borrow
+  --> $DIR/issue-51191.rs:27:16
+   |
+LL |     fn mtblref(&mut self) {
+   |                ^^^^^^^^^
+help: try removing `&mut` here
+  --> $DIR/issue-51191.rs:28:9
+   |
 LL |         (&mut self).bar();
    |         ^^^^^^^^^^^
-   |         |
-   |         cannot borrow as mutable
-   |         help: try removing `&mut` here
 
 error: aborting due to 5 previous errors; 1 warning emitted
 
index 84c0dec2fe5cd374e51efdd84423b5d4d5ce55f8..e61db71220e8584776c07eaf24a336b36e889188 100644 (file)
@@ -7,8 +7,8 @@ fn all_previous_tests_may_be_done(y: &mut (bool, bool)) {
     let r = &mut y.1;
     // We don't actually test y.1 to select the second arm, but we don't want
     // borrowck results to be based on the order we match patterns.
-    match y {
-        (false, true) => 1, //~ ERROR cannot use `y.1` because it was mutably borrowed
+    match y { //~ ERROR cannot use `y.1` because it was mutably borrowed
+        (false, true) => 1,
         (true, _) => {
             r;
             2
index eab89658e79be3fb6dc28c1f0c901de52b058826..0ce83849b9f9421cedcc2db50a52d759e78b13bb 100644 (file)
@@ -1,12 +1,12 @@
 error[E0503]: cannot use `y.1` because it was mutably borrowed
-  --> $DIR/match-cfg-fake-edges2.rs:11:17
+  --> $DIR/match-cfg-fake-edges2.rs:10:5
    |
 LL |     let r = &mut y.1;
    |             -------- borrow of `y.1` occurs here
 ...
-LL |         (false, true) => 1,
-   |                 ^^^^ use of borrowed `y.1`
-LL |         (true, _) => {
+LL |     match y {
+   |     ^^^^^^^ use of borrowed `y.1`
+...
 LL |             r;
    |             - borrow later used here
 
index aba0a7f71f5c1ff2505ecf54abd1cb0bdd6a2dae..447dabeb47e598f619a5d916c1dd1b11853079cd 100644 (file)
@@ -45,8 +45,9 @@ fn enum_example(mut e: E) {
         E::W => panic!(),
     };
     match e { // Don't know that E uses a tag for its discriminant
+        //~^ ERROR
         _ if false => (),
-        E::V(_, r) => (), //~ ERROR
+        E::V(_, r) => (),
         E::W => (),
     }
     x;
@@ -58,8 +59,9 @@ fn indirect_enum_example(mut f: &mut E) {
         E::W => panic!(),
     };
     match f { // Don't know that E uses a tag for its discriminant
+        //~^ ERROR
         _ if false => (),
-        E::V(_, r) => (), //~ ERROR
+        E::V(_, r) => (),
         E::W => (),
     }
     x;
@@ -77,7 +79,8 @@ fn match_on_muatbly_borrowed_ref(mut p: &bool) {
 fn match_on_borrowed(mut t: bool) {
     let x = &mut t;
     match t {
-        true => (), //~ ERROR
+        //~^ ERROR
+        true => (),
         false => (),
     }
     x;
index f9c9a84632212376d32108a57c1043bb134ec80c..2121b59b02da375c2bd06a65609f6a3f0f4d29dd 100644 (file)
@@ -1,41 +1,40 @@
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/match-on-borrowed.rs:49:9
+  --> $DIR/match-on-borrowed.rs:47:11
    |
 LL |         E::V(ref mut x, _) => x,
    |              --------- borrow of `e.0` occurs here
 ...
-LL |         E::V(_, r) => (),
-   |         ^^^^^^^^^^ use of borrowed `e.0`
+LL |     match e { // Don't know that E uses a tag for its discriminant
+   |           ^ use of borrowed `e.0`
 ...
 LL |     x;
    |     - borrow later used here
 
 error[E0503]: cannot use `*f` because it was mutably borrowed
-  --> $DIR/match-on-borrowed.rs:62:9
+  --> $DIR/match-on-borrowed.rs:61:11
    |
 LL |         E::V(ref mut x, _) => x,
    |              --------- borrow of `f.0` occurs here
 ...
-LL |         E::V(_, r) => (),
-   |         ^^^^^^^^^^ use of borrowed `f.0`
+LL |     match f { // Don't know that E uses a tag for its discriminant
+   |           ^ use of borrowed `f.0`
 ...
 LL |     x;
    |     - borrow later used here
 
 error[E0503]: cannot use `t` because it was mutably borrowed
-  --> $DIR/match-on-borrowed.rs:80:9
+  --> $DIR/match-on-borrowed.rs:81:5
    |
 LL |     let x = &mut t;
    |             ------ borrow of `t` occurs here
 LL |     match t {
-LL |         true => (),
-   |         ^^^^ use of borrowed `t`
+   |     ^^^^^^^ use of borrowed `t`
 ...
 LL |     x;
    |     - borrow later used here
 
 error[E0381]: use of possibly-uninitialized variable: `n`
-  --> $DIR/match-on-borrowed.rs:90:11
+  --> $DIR/match-on-borrowed.rs:93:11
    |
 LL |     match n {}
    |           ^ use of possibly-uninitialized `n`
diff --git a/src/test/ui/obsolete-in-place/bad.bad.stderr b/src/test/ui/obsolete-in-place/bad.bad.stderr
deleted file mode 100644 (file)
index d895981..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error: expected expression, found keyword `in`
-  --> $DIR/bad.rs:10:5
-   |
-LL |     in(foo) { bar };
-   |     ^^ expected expression
-
-error[E0282]: type annotations needed
-  --> $DIR/bad.rs:9:8
-   |
-LL |     let (x, y, foo, bar);
-   |         ---------------- consider giving the pattern a type
-LL |     x <- y;
-   |        ^^^ cannot infer type
-   |
-   = note: type must be known at this point
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr
new file mode 100644 (file)
index 0000000..fcdc070
--- /dev/null
@@ -0,0 +1,5 @@
+thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: issue_47429_short_backtraces::main
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
index 015ab8fdd80df6b234e034992bc574ba1b44c559..35ecfc0b27158720d8e493fcb31efd2ef1c62724 100644 (file)
 // ignore-emscripten no panic or subprocess support
 // ignore-sgx no subprocess support
 
+// NOTE(eddyb) output differs between symbol mangling schemes
+// revisions: legacy v0
+// [legacy] compile-flags: -Zsymbol-mangling-version=legacy
+//     [v0] compile-flags: -Zsymbol-mangling-version=v0
+
 fn main() {
     panic!()
 }
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.run.stderr
deleted file mode 100644 (file)
index 3287963..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:16:5
-stack backtrace:
-   0: std::panicking::begin_panic
-   1: issue_47429_short_backtraces::main
-note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr
new file mode 100644 (file)
index 0000000..1cbf117
--- /dev/null
@@ -0,0 +1,5 @@
+thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:21:5
+stack backtrace:
+   0: std::panicking::begin_panic::<&str>
+   1: issue_47429_short_backtraces::main
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
index 6dfe7aad6ea64b3412b04c781e26fcd907c0744c..d38b98a19011709225dc8765f46739ada2e50b9a 100644 (file)
@@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `]`
   --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
@@ -12,11 +13,11 @@ error: expected expression, found `]`
 LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
    |                                        ^ expected expression
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:9:35
    |
 LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
-   |                                   ^ expected one of 7 possible tokens
+   |                                   ^ expected one of 8 possible tokens
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:11:36
@@ -24,7 +25,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `)`
   --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
@@ -38,7 +40,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
    |                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `)`
   --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
@@ -52,7 +55,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
    |                                    ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
@@ -60,7 +64,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
    |                                 ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
@@ -68,13 +73,14 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
    |                                 ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `#`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
-   |                                  ^ expected one of 7 possible tokens
+   |                                  ^ expected one of 8 possible tokens
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:25:35
@@ -82,7 +88,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
    |                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
@@ -90,7 +97,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
    |                                        ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
@@ -98,7 +106,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
    |                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
@@ -106,7 +115,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
    |                                        ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected expression, found `..`
   --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
@@ -126,7 +136,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
    |                                         ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
@@ -134,7 +145,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
    |                                             ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
@@ -151,7 +163,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
    |                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
@@ -174,7 +187,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
    |                                              ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
@@ -200,7 +214,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
    |                                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:57:45
@@ -217,7 +232,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
    |                                              ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:61:48
@@ -240,7 +256,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
    |                                                      ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/attr-stmt-expr-attr-bad.rs:67:53
@@ -266,7 +283,8 @@ error: an inner attribute is not permitted in this context
 LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
    |                                                                   ^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:74:32
@@ -276,7 +294,8 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
    |                        |
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:76:32
@@ -286,37 +305,56 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
    |                        |
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); }
+   | 
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; }
+   | 
 
 error: an inner attribute is not permitted following an outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
    |
 LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
-   |                        ------- ^^^^^^^^ not permitted following an outer attribute
-   |                        |
+   |                        ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation
+   |                        |       |
+   |                        |       not permitted following an outer attribute
    |                        previous outer attribute
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the item macro invocation, change the attribute from inner to outer style
+   |
+LL - #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
+LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; }
+   | 
 
 error[E0586]: inclusive range with no end
   --> $DIR/attr-stmt-expr-attr-bad.rs:88:35
@@ -372,11 +410,11 @@ error: unexpected token: `#`
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
    |                                  ^
 
-error: expected one of `.`, `;`, `?`, or an operator, found `#`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
-   |                                  ^ expected one of `.`, `;`, `?`, or an operator
+   |                                  ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: unexpected token: `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
@@ -384,11 +422,11 @@ error: unexpected token: `#`
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
    |                                  ^
 
-error: expected one of `.`, `;`, `?`, or an operator, found `#`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
    |
 LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
-   |                                  ^ expected one of `.`, `;`, `?`, or an operator
+   |                                  ^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: expected statement after outer attribute
   --> $DIR/attr-stmt-expr-attr-bad.rs:108:37
index 400a0276b3b608f8719535175c3ad846dd52b2c4..3cec61fe41eea9170d3bbfcb4743c47d4e02d7d9 100644 (file)
@@ -3,8 +3,16 @@ error: an inner attribute is not permitted in this context
    |
 LL | #![lang = "foo"]
    | ^^^^^^^^^^^^^^^^
+LL |
+LL | fn foo() {}
+   | ----------- the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![lang = "foo"]
+LL + #[lang = "foo"]
+   | 
 
 error[E0522]: definition of an unknown language item: `foo`
   --> $DIR/attr.rs:5:1
index 7a187a0518af9d7f404c031d1c3be8f25dbf175f..4ae4549ea58966346c2d0d6994ae0a8d0407d8c1 100644 (file)
@@ -9,10 +9,10 @@ struct S<
     T: Tr +, // OK
     T: ?'a, //~ ERROR `?` may only modify trait bounds, not lifetime bounds
 
-    T: ?const Tr, // OK
-    T: ?const ?Tr, // OK
-    T: ?const Tr + 'a, // OK
-    T: ?const 'a, //~ ERROR `?const` may only modify trait bounds, not lifetime bounds
+    T: ~const Tr, // OK
+    T: ~const ?Tr, // OK
+    T: ~const Tr + 'a, // OK
+    T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds
 >;
 
 fn main() {}
index 9a1f2ed398240f48f8da6b140af1848eee8b5fea..005bc1e54bd00421358c18ea1f832e595df62041 100644 (file)
@@ -4,10 +4,10 @@ error: `?` may only modify trait bounds, not lifetime bounds
 LL |     T: ?'a,
    |        ^
 
-error: `?const` may only modify trait bounds, not lifetime bounds
+error: `~const` may only modify trait bounds, not lifetime bounds
   --> $DIR/bounds-type.rs:15:8
    |
-LL |     T: ?const 'a,
+LL |     T: ~const 'a,
    |        ^^^^^^
 
 error: aborting due to 2 previous errors
index be52a0afd46b76ca90ec86cac02c774467656b54..b7c1847fc7c0dfe7bd0c7c0b8b06c7facdb25563 100644 (file)
@@ -5,6 +5,11 @@ LL |     if true /*!*/ {}
    |             ^^^^^
    |
    = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL -     if true /*!*/ {}
+LL +     if true /**/ {}
+   | 
 
 error: outer attributes are not allowed on `if` and `else` branches
   --> $DIR/doc-comment-in-if-statement.rs:2:13
index c1e9e7a427f89696d50a8f6b2a46166c7a9f908c..404800ee15bdda66cd866cf80de57b7a161ab4c1 100644 (file)
@@ -8,8 +8,16 @@ LL | |  */
 LL | 
 LL |   #![recursion_limit="100"]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
+LL |
+LL |   fn main() {}
+   |   ------------ the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![recursion_limit="100"]
+LL + #[recursion_limit="100"]
+   | 
 
 error: aborting due to previous error
 
index e1bf2cca1c9635b5303b19a03a0b01c98abe5d05..1adac74590881d078877bedb31adcae2444a5168 100644 (file)
@@ -6,8 +6,15 @@ LL | #[feature(lang_items)]
 LL | 
 LL | #![recursion_limit="100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
+LL | fn main() {}
+   | ------------ the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![recursion_limit="100"]
+LL + #[recursion_limit="100"]
+   | 
 
 error: aborting due to previous error
 
index ff90cb97096f71cce38cf5f103fc755918a03ca9..1e6294ebe169152935407c91a40c0e5bd60dda6d 100644 (file)
@@ -1,8 +1,8 @@
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-10636-1.rs:4:1
+  --> $DIR/issue-10636-1.rs:1:12
    |
 LL | struct Obj {
-   |            - unclosed delimiter
+   |            ^ unclosed delimiter
 ...
 LL | )
    | ^ mismatched closing delimiter
index 5b9a9b7f06c39aa9fd06b551bf50509d27e9cc58..d4f2da9e3ab6f5b4c6d1c51f0a42a1fd8c0fb9c2 100644 (file)
@@ -1,8 +1,8 @@
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/issue-10636-2.rs:5:25
+  --> $DIR/issue-10636-2.rs:5:15
    |
 LL |     option.map(|some| 42;
-   |               -         ^ help: `)` may belong here
+   |               ^         ^ help: `)` may belong here
    |               |
    |               unclosed delimiter
 
diff --git a/src/test/ui/parser/issue-30318.fixed b/src/test/ui/parser/issue-30318.fixed
new file mode 100644 (file)
index 0000000..71fc821
--- /dev/null
@@ -0,0 +1,27 @@
+// run-rustfix
+#![allow(unused)]
+fn foo() { }
+
+/// Misplaced comment...
+//~^ ERROR expected outer doc comment
+fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+#[test] //~ ERROR an inner attribute is not permitted in this context
+fn baz() { } //~ NOTE the inner attribute doesn't annotate this function
+//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually
+
+/** Misplaced comment... */
+//~^ ERROR expected outer doc comment
+fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+fn main() { }
+
+// Misplaced comment...
+//~^ ERROR expected outer doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+//~| NOTE other attributes here
+/* Misplaced comment... */
+//~^ ERROR expected outer doc comment
+//~| NOTE this doc comment doesn't document anything
+//~| ERROR expected item after doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
index 38e30de716d0a1491977966b0795b3148e851934..465dca2ff82247e12efb75dc9d15c6941ae56a36 100644 (file)
@@ -1,7 +1,27 @@
+// run-rustfix
+#![allow(unused)]
 fn foo() { }
 
 //! Misplaced comment...
 //~^ ERROR expected outer doc comment
-//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+fn bar() { } //~ NOTE the inner doc comment doesn't annotate this function
+
+#![test] //~ ERROR an inner attribute is not permitted in this context
+fn baz() { } //~ NOTE the inner attribute doesn't annotate this function
+//~^^ NOTE inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually
+
+/*! Misplaced comment... */
+//~^ ERROR expected outer doc comment
+fn bat() { } //~ NOTE the inner doc comment doesn't annotate this function
 
 fn main() { }
+
+//! Misplaced comment...
+//~^ ERROR expected outer doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+//~| NOTE other attributes here
+/*! Misplaced comment... */
+//~^ ERROR expected outer doc comment
+//~| NOTE this doc comment doesn't document anything
+//~| ERROR expected item after doc comment
+//~| NOTE inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
index b3a27f19851711db634f74fcfa146856ee6d212d..7e7108845546a1e1bf47b545f62c44c6556af4c6 100644 (file)
@@ -1,11 +1,81 @@
 error[E0753]: expected outer doc comment
-  --> $DIR/issue-30318.rs:3:1
+  --> $DIR/issue-30318.rs:5:1
+   |
+LL | //! Misplaced comment...
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn bar() { }
+   | ------------ the inner doc comment doesn't annotate this function
+   |
+help: to annotate the function, change the doc comment from inner to outer style
+   |
+LL | /// Misplaced comment...
+   |   ~
+
+error: an inner attribute is not permitted in this context
+  --> $DIR/issue-30318.rs:9:1
+   |
+LL | #![test]
+   | ^^^^^^^^
+LL | fn baz() { }
+   | ------------ the inner attribute doesn't annotate this function
+   |
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL - #![test]
+LL + #[test]
+   | 
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:13:1
+   |
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | fn bat() { }
+   | ------------ the inner doc comment doesn't annotate this function
+   |
+help: to annotate the function, change the doc comment from inner to outer style
+   |
+LL | /** Misplaced comment... */
+   |   ~
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:19:1
    |
 LL | //! Misplaced comment...
    | ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL - //! Misplaced comment...
+LL + // Misplaced comment...
+   | 
+
+error[E0753]: expected outer doc comment
+  --> $DIR/issue-30318.rs:23:1
+   |
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: you might have meant to write a regular comment
+   |
+LL - /*! Misplaced comment... */
+LL + /* Misplaced comment... */
+   | 
+
+error: expected item after doc comment
+  --> $DIR/issue-30318.rs:23:1
+   |
+LL | //! Misplaced comment...
+   | ------------------------ other attributes here
+...
+LL | /*! Misplaced comment... */
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
 
-error: aborting due to previous error
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0753`.
index f242c1d29372f2ae4a04718b0f1b4164008efa14..d3a97e89f9abb229372b1a8b5e98aefdddf0e474 100644 (file)
@@ -2,4 +2,5 @@ fn main() {
     let unused = ();
 
     #![allow(unused_variables)] //~ ERROR not permitted in this context
+    fn foo() {}
 }
index c0d4ce1243e015f0dee62a0a8ab701602600286a..6abe266d4e90eae5405c331f5e3ed99b72929d09 100644 (file)
@@ -3,8 +3,15 @@ error: an inner attribute is not permitted in this context
    |
 LL |     #![allow(unused_variables)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     fn foo() {}
+   |     ----------- the inner attribute doesn't annotate this function
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+help: to annotate the function, change the attribute from inner to outer style
+   |
+LL -     #![allow(unused_variables)]
+LL +     #[allow(unused_variables)]
+   | 
 
 error: aborting due to previous error
 
index f1abb40ed7a739a4dde60dfa33edb4f330f0879d..2afb26d17583471dc52cc76350436f6e82b8be39 100644 (file)
@@ -1,8 +1,8 @@
 error: expected one of `)`, `,`, or `:`, found `>`
-  --> $DIR/issue-58856-1.rs:3:14
+  --> $DIR/issue-58856-1.rs:3:9
    |
 LL |     fn b(self>
-   |         -    ^ help: `)` may belong here
+   |         ^    ^ help: `)` may belong here
    |         |
    |         unclosed delimiter
 
index 303b5eacc3296c277520d103960605b038b88b6c..627dd389059cd78baed0a5970066981ca8dda323 100644 (file)
@@ -1,8 +1,8 @@
 error: expected one of `)` or `,`, found `->`
-  --> $DIR/issue-58856-2.rs:6:26
+  --> $DIR/issue-58856-2.rs:6:19
    |
 LL |     fn how_are_you(&self -> Empty {
-   |                   -     -^^
+   |                   ^     -^^
    |                   |     |
    |                   |     help: `)` may belong here
    |                   unclosed delimiter
index e3b7f4ad420e8a200972dae53e79389a25440738..210ef700cd4bc27dd4956cc14314f8c387f01bf0 100644 (file)
@@ -17,10 +17,10 @@ LL |     }
    |     - item list ends here
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-60075.rs:6:10
+  --> $DIR/issue-60075.rs:4:31
    |
 LL |     fn qux() -> Option<usize> {
-   |                               - unclosed delimiter
+   |                               ^ unclosed delimiter
 LL |         let _ = if true {
 LL |         });
    |          ^ mismatched closing delimiter
index 3065d642fe105267acc3db44e392e04d65facbd9..51d835e7329884b870e019e161a091169d03b942 100644 (file)
@@ -21,10 +21,10 @@ LL |
    |  ^
 
 error: expected one of `,` or `}`, found `{`
-  --> $DIR/issue-62973.rs:6:25
+  --> $DIR/issue-62973.rs:6:8
    |
 LL | fn p() { match s { v, E { [) {) }
-   |        -       -       -^ expected one of `,` or `}`
+   |        ^       -       -^ expected one of `,` or `}`
    |        |       |       |
    |        |       |       help: `}` may belong here
    |        |       while parsing this struct
@@ -56,18 +56,18 @@ LL |
    |  ^ expected one of `.`, `?`, `{`, or an operator
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-62973.rs:6:28
+  --> $DIR/issue-62973.rs:6:27
    |
 LL | fn p() { match s { v, E { [) {) }
-   |                           -^ mismatched closing delimiter
+   |                           ^^ mismatched closing delimiter
    |                           |
    |                           unclosed delimiter
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/issue-62973.rs:6:31
+  --> $DIR/issue-62973.rs:6:30
    |
 LL | fn p() { match s { v, E { [) {) }
-   |                              -^ mismatched closing delimiter
+   |                              ^^ mismatched closing delimiter
    |                              |
    |                              unclosed delimiter
 
index 4766dfafea1c9abf71ed769eff3c19a33f14922f..cfdd99d1434aef0f17965b4032a77111c9152e0d 100644 (file)
@@ -13,10 +13,10 @@ LL | impl W <s(f;Y(;]
    |            ^ expected one of 7 possible tokens
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-63116.rs:3:16
+  --> $DIR/issue-63116.rs:3:14
    |
 LL | impl W <s(f;Y(;]
-   |              - ^ mismatched closing delimiter
+   |              ^ ^ mismatched closing delimiter
    |              |
    |              unclosed delimiter
 
index 332711df72f3c4b4cd90ea485cdf2e5b48193f55..6cbab855c7636ad9e91692c12d9cc5ec424898de 100644 (file)
@@ -5,10 +5,10 @@ LL | fn f() { |[](* }
    |             ^ expected one of `,` or `:`
 
 error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:14
+  --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
    |
 LL | fn f() { |[](* }
-   |             -^ help: `)` may belong here
+   |             ^^ help: `)` may belong here
    |             |
    |             unclosed delimiter
 
index f20ec75535354aec7a98c0ab439217eb64458cc7..34f1397ce1d5bb62afeaf5a567a938801b75c092 100644 (file)
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
    |
 LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             -              ^ mismatched closing delimiter
+   |             -             ^              ^ mismatched closing delimiter
    |             |             |
    |             |             unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
    |
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
    |
 LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             -              ^ mismatched closing delimiter
+   |             -             ^              ^ mismatched closing delimiter
    |             |             |
    |             |             unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
    |
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
    |
 LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             -              ^ mismatched closing delimiter
+   |             -             ^              ^ mismatched closing delimiter
    |             |             |
    |             |             unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
    |
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:42
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
    |
 LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             -              ^ mismatched closing delimiter
+   |             -             ^              ^ mismatched closing delimiter
    |             |             |
    |             |             unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:36
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
    |
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          -           ^ mismatched closing delimiter
+   |             -          ^           ^ mismatched closing delimiter
    |             |          |
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
index 6f9af73b039e4aa28e0b463edbce423b00797eb0..1446a796fa0d5ba81825cad5d9e846dfd8bcd510 100644 (file)
@@ -1,6 +1,6 @@
 fn main() {
     let a = std::process::Command::new("echo")
         .arg("1")
-        ,arg("2") //~ ERROR expected one of `.`, `;`, `?`, or an operator, found `,`
+        ,arg("2") //~ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `,`
         .output();
 }
index 3819fd92a9e2138914005123c934596dc6e16d87..477fa09f495e23c315b7702283db3a1948dd407d 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, or an operator, found `,`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `,`
   --> $DIR/issue-72253.rs:4:9
    |
 LL |         .arg("1")
-   |                  - expected one of `.`, `;`, `?`, or an operator
+   |                  - expected one of `.`, `;`, `?`, `else`, or an operator
 LL |         ,arg("2")
    |         ^ unexpected token
 
index 0f20073591598dc13ef724ac434e98ea7a90be75..919585877cf9cfa899c7e234188c72a108f0c97c 100644 (file)
@@ -2,8 +2,8 @@ fn main() {
     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
     //~^ ERROR expected one of `>`, a const expression
     //~| ERROR expected one of `>`, a const expression, lifetime, or type, found `}`
-    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
-    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
-    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
+    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
+    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
+    //~| ERROR expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
 }
 //~^ ERROR expected one of `,`, `:`, `=`, or `>`, found `}`
index d667a4977d0d31a815ed0b6aa2da6491ce660575..5b9cc53baa5eb891d247ca8a950ca9bd2c0b0574 100644 (file)
@@ -7,11 +7,11 @@ LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
    |                                         |          help: use `=` if you meant to assign
    |                                         while parsing the type for `inner_local`
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:65
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |                                                                 ^ expected one of 7 possible tokens
+   |                                                                 ^ expected one of 8 possible tokens
 
 error: expected one of `,`, `:`, `=`, or `>`, found `}`
   --> $DIR/issue-84117.rs:8:1
@@ -33,17 +33,17 @@ LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
    |                                         |          help: use `=` if you meant to assign
    |                                         while parsing the type for `inner_local`
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:65
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |                                                                 ^ expected one of 7 possible tokens
+   |                                                                 ^ expected one of 8 possible tokens
 
-error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, or an operator, found `,`
+error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `,`
   --> $DIR/issue-84117.rs:2:33
    |
 LL |     let outer_local:e_outer<&str, { let inner_local:e_inner<&str, }
-   |                                 ^ expected one of 7 possible tokens
+   |                                 ^ expected one of 8 possible tokens
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/parser/issue-87812-path.rs b/src/test/ui/parser/issue-87812-path.rs
new file mode 100644 (file)
index 0000000..b887808
--- /dev/null
@@ -0,0 +1,11 @@
+macro_rules! foo {
+    ( $f:path ) => {{
+        let _: usize = $f; //~ERROR
+    }};
+}
+
+struct Baz;
+
+fn main() {
+    foo!(Baz);
+}
diff --git a/src/test/ui/parser/issue-87812-path.stderr b/src/test/ui/parser/issue-87812-path.stderr
new file mode 100644 (file)
index 0000000..0c8e6fd
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-87812-path.rs:3:24
+   |
+LL |         let _: usize = $f;
+   |                -----   ^^ expected `usize`, found struct `Baz`
+   |                |
+   |                expected due to this
+...
+LL |     foo!(Baz);
+   |     ---------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/issue-87812.rs b/src/test/ui/parser/issue-87812.rs
new file mode 100644 (file)
index 0000000..0ba87b9
--- /dev/null
@@ -0,0 +1,13 @@
+#![deny(break_with_label_and_loop)]
+
+macro_rules! foo {
+    ( $f:block ) => {
+        '_l: loop {
+            break '_l $f; //~ERROR
+        }
+    };
+}
+
+fn main() {
+    let x = foo!({ 3 });
+}
diff --git a/src/test/ui/parser/issue-87812.stderr b/src/test/ui/parser/issue-87812.stderr
new file mode 100644 (file)
index 0000000..d61ee23
--- /dev/null
@@ -0,0 +1,22 @@
+error: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression
+  --> $DIR/issue-87812.rs:6:13
+   |
+LL |             break '_l $f;
+   |             ^^^^^^^^^^^^
+...
+LL |     let x = foo!({ 3 });
+   |             ----------- in this macro invocation
+   |
+note: the lint level is defined here
+  --> $DIR/issue-87812.rs:1:9
+   |
+LL | #![deny(break_with_label_and_loop)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: wrap this expression in parentheses
+   |
+LL |             break '_l ($f);
+   |                       +  +
+
+error: aborting due to previous error
+
index 93c5ab383d48804bf44999e82ca67cda69ea0f69..077d318004896f6dbf0dfe60e65e96ae6647690a 100644 (file)
@@ -1,8 +1,8 @@
 error: mismatched closing delimiter: `)`
-  --> $DIR/macro-mismatched-delim-brace-paren.rs:6:5
+  --> $DIR/macro-mismatched-delim-brace-paren.rs:4:10
    |
 LL |     foo! {
-   |          - unclosed delimiter
+   |          ^ unclosed delimiter
 LL |         bar, "baz", 1, 2.0
 LL |     )
    |     ^ mismatched closing delimiter
index 424c7a60c196f06ce9707d048e40bddae1cb85dc..967a3e6fdc11b76a56a6f6cf88cf6eba459ad50a 100644 (file)
@@ -10,10 +10,10 @@ LL | }
    | ^ unexpected closing delimiter
 
 error: mismatched closing delimiter: `}`
-  --> $DIR/macro-mismatched-delim-paren-brace.rs:4:5
+  --> $DIR/macro-mismatched-delim-paren-brace.rs:2:10
    |
 LL |     foo! (
-   |          - unclosed delimiter
+   |          ^ unclosed delimiter
 LL |         bar, "baz", 1, 2.0
 LL |     }
    |     ^ mismatched closing delimiter
index f0ec79e53574a1ad5939ee8647d71ad61c02d5c7..8d9636d401c1ed0fa83414165c00fdffac342d1b 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, or an operator, found `""`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `""`
   --> $DIR/issue-37234.rs:3:19
    |
 LL |         let x = 5 "";
-   |                   ^^ expected one of `.`, `;`, `?`, or an operator
+   |                   ^^ expected one of `.`, `;`, `?`, `else`, or an operator
 ...
 LL |     failed!();
    |     ---------- in this macro invocation
index a24dfa761a60ff3d9ef3b4c20cb4de6c8d961684..f68d177c01f1fe04061871d6a4aa7d9ccbd0ea69 100644 (file)
@@ -1,6 +1,6 @@
 macro_rules! m {
     ($($e1:expr),*; $($e2:expr),*) => {
-        $( let x = $e1 )*; //~ ERROR expected one of `.`, `;`, `?`, or
+        $( let x = $e1 )*; //~ ERROR expected one of `.`, `;`, `?`, `else`, or
         $( println!("{}", $e2) )*;
     }
 }
index 68f0f440c46b923585394963b72c45c9cdb208eb..72f76b6fe3f548ce62809f6a58259d212afec891 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, or an operator, found keyword `let`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found keyword `let`
   --> $DIR/missing-semicolon.rs:3:12
    |
 LL |         $( let x = $e1 )*;
-   |            ^^^ expected one of `.`, `;`, `?`, or an operator
+   |            ^^^ expected one of `.`, `;`, `?`, `else`, or an operator
 ...
 LL | fn main() { m!(0, 0; 0, 0); }
    |             --------------- in this macro invocation
index cd3da4c71f0b5685fbffd5d6b189e279c455f42a..0980d033fe73ad51b7c4c32bace40a0c04c83f0f 100644 (file)
@@ -5,10 +5,10 @@ LL |     let x = y.;
    |               ^
 
 error: mismatched closing delimiter: `)`
-  --> $DIR/parser-recovery-2.rs:6:5
+  --> $DIR/parser-recovery-2.rs:4:14
    |
 LL |     fn bar() {
-   |              - unclosed delimiter
+   |              ^ unclosed delimiter
 LL |         let x = foo();
 LL |     )
    |     ^ mismatched closing delimiter
index 931839fb282d15e43e8880f6ca22e35fbf62e6d4..2c917a24e908aa1e030356b86fb0d6ab83beee34 100644 (file)
@@ -2,5 +2,5 @@
 
 pub fn main() {
     let r = 1..2..3;
-    //~^ ERROR expected one of `.`, `;`, `?`, or an operator, found `..`
+    //~^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `..`
 }
index f866ea59983b6db54bcc73237fd09b160340168b..340167f1804e37a868dd6beac1addfd96e984d9d 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, or an operator, found `..`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..`
   --> $DIR/range-3.rs:4:17
    |
 LL |     let r = 1..2..3;
-   |                 ^^ expected one of `.`, `;`, `?`, or an operator
+   |                 ^^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: aborting due to previous error
 
index 20af9567205796cff3dc146b81d4c68fb460ee04..c970c96de849094b14c1f2e637abee323778ff32 100644 (file)
@@ -2,5 +2,5 @@
 
 pub fn main() {
     let r = ..1..2;
-    //~^ ERROR expected one of `.`, `;`, `?`, or an operator, found `..`
+    //~^ ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `..`
 }
index dcb85170c1d3b8eaf33be950308a45e6e3c660c8..720d489389bfb7876f3b69253fe6d58f9030c40b 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `.`, `;`, `?`, or an operator, found `..`
+error: expected one of `.`, `;`, `?`, `else`, or an operator, found `..`
   --> $DIR/range-4.rs:4:16
    |
 LL |     let r = ..1..2;
-   |                ^^ expected one of `.`, `;`, `?`, or an operator
+   |                ^^ expected one of `.`, `;`, `?`, `else`, or an operator
 
 error: aborting due to previous error
 
index 808903d9c62f3e559d80db61cc8eff9b05cf6fc3..bf4005698a3d61da810e0ff781b3682998e98d39 100644 (file)
@@ -4,7 +4,8 @@ error: an inner attribute is not permitted in this context
 LL |     let a = #![allow(warnings)] (1, 2);
    |             ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:10:14
@@ -12,7 +13,8 @@ error: an inner attribute is not permitted in this context
 LL |     let b = (#![allow(warnings)] 1, 2);
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:15:10
@@ -20,7 +22,8 @@ error: an inner attribute is not permitted in this context
 LL |         (#![allow(warnings)] 1, 2)
    |          ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:21:18
@@ -28,7 +31,8 @@ error: an inner attribute is not permitted in this context
 LL |         let e = (#![allow(warnings)] 1, 2);
    |                  ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:26:14
@@ -36,7 +40,8 @@ error: an inner attribute is not permitted in this context
 LL |     let e = [#![allow(warnings)] 1, 2];
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:29:14
@@ -44,7 +49,8 @@ error: an inner attribute is not permitted in this context
 LL |     let f = [#![allow(warnings)] 1; 0];
    |              ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: an inner attribute is not permitted in this context
   --> $DIR/stmt_expr_attrs_placement.rs:36:24
@@ -52,7 +58,8 @@ error: an inner attribute is not permitted in this context
 LL |     let h = MyStruct { #![allow(warnings)] field: 0 };
    |                        ^^^^^^^^^^^^^^^^^^^
    |
-   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.
+   = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+   = note: outer attributes, like `#[test]`, annotate the item following them
 
 error: aborting due to 7 previous errors
 
index 650ab57226187a4c497221e76b5d27874e87cc23..b5258eebb90adf774132336d9078bc3226aa48c8 100644 (file)
@@ -6,7 +6,7 @@ fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
 fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
 
 fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
-//~^ ERROR expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found `{`
+//~^ ERROR expected one of `!`, `(`, `)`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
 //~| ERROR at least one trait is required for an object type
 
 fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
index 1ae0205615cb11f952c6618d8d545df23cf96020..ee638d8a4f5ecf20c214d76f1dcfcb2687e1fb2c 100644 (file)
@@ -22,11 +22,11 @@ error: expected parameter name, found `{`
 LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
    |                 ^ expected parameter name
 
-error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, lifetime, or path, found `{`
+error: expected one of `!`, `(`, `)`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
   --> $DIR/trait-object-delimiters.rs:8:17
    |
 LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
-   |                -^ expected one of 8 possible tokens
+   |                -^ expected one of 9 possible tokens
    |                |
    |                help: missing `,`
 
index 00861a5a3d49a1096b279a1ea42c2534532fa334..1366ef1bba8bfb3956ae538dc3f706ff4474da8d 100644 (file)
@@ -1,10 +1,10 @@
 error: mismatched closing delimiter: `}`
-  --> $DIR/unclosed_delim_mod.rs:7:1
+  --> $DIR/unclosed_delim_mod.rs:5:7
    |
 LL | pub fn new() -> Result<Value, ()> {
    |                                   - closing delimiter possibly meant for this
 LL |     Ok(Value {
-   |       - unclosed delimiter
+   |       ^ unclosed delimiter
 LL |     }
 LL | }
    | ^ mismatched closing delimiter
index 9c1670721236752b227372cf9bc782a104a5066d..a46d020b9672e13cff2face8c0fc650400acb709 100644 (file)
@@ -1,10 +1,10 @@
 error: mismatched closing delimiter: `}`
-  --> $DIR/unclosed_delim_mod.rs:7:1
+  --> $DIR/unclosed_delim_mod.rs:5:7
    |
 LL | pub fn new() -> Result<Value, ()> {
    |                                   - closing delimiter possibly meant for this
 LL |     Ok(Value {
-   |       - unclosed delimiter
+   |       ^ unclosed delimiter
 LL |     }
 LL | }
    | ^ mismatched closing delimiter
index d29a68f8214814f86b144da165da89d8bfa307a6..438fe9c47eac1ac447ef28181a9b832e7ae4a8fb 100644 (file)
@@ -8,10 +8,10 @@ LL | fn main() {}
    |              ^
 
 error: expected one of `,`, `::`, `as`, or `}`, found `;`
-  --> $DIR/use-unclosed-brace.rs:4:19
+  --> $DIR/use-unclosed-brace.rs:4:10
    |
 LL | use foo::{bar, baz;
-   |          -        ^
+   |          ^        ^
    |          |        |
    |          |        expected one of `,`, `::`, `as`, or `}`
    |          |        help: `}` may belong here
diff --git a/src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs b/src/test/ui/pattern/auxiliary/declarations-for-tuple-field-count-errors.rs
new file mode 100644 (file)
index 0000000..f7373c4
--- /dev/null
@@ -0,0 +1,20 @@
+pub struct Z0;
+pub struct Z1();
+
+pub struct S(pub u8, pub u8, pub u8);
+pub struct M(
+    pub u8,
+    pub u8,
+    pub u8,
+);
+
+pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+
+pub enum E2 {
+    S(u8, u8, u8),
+    M(
+        u8,
+        u8,
+        u8,
+    ),
+}
index 7f5da8f3c2dcc3c788a22646245b02da1982a3f7..75a231f6b4ba32fee613d9327a7bd82df5782e05 100644 (file)
@@ -13,7 +13,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has
   --> $DIR/issue-67037-pat-tup-scrut-ty-diff-less-fields.rs:19:9
    |
 LL | struct P<T>(T); // 1 type parameter wanted
-   | --------------- tuple struct defined here
+   |             - tuple struct has 1 field
 ...
 LL |     let P() = U {};
    |         ^^^ expected 1 field, found 0
index 7d998af7fb38896d85beed9e6759b0c1b118cce5..7443946c013f7294bb51bed7e9389897ce75873a 100644 (file)
@@ -19,13 +19,13 @@ LL |         E::A(x @ ..) => {
    = note: only allowed in tuple, tuple struct, and slice patterns
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/issue-74539.rs:8:9
+  --> $DIR/issue-74539.rs:8:14
    |
 LL |     A(u8, u8),
-   |     --------- tuple variant defined here
+   |       --  -- tuple variant has 2 fields
 ...
 LL |         E::A(x @ ..) => {
-   |         ^^^^^^^^^^^^ expected 2 fields, found 1
+   |              ^^^^^^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.rs b/src/test/ui/pattern/pat-tuple-field-count-cross.rs
new file mode 100644 (file)
index 0000000..b63da4e
--- /dev/null
@@ -0,0 +1,57 @@
+// aux-build:declarations-for-tuple-field-count-errors.rs
+
+extern crate declarations_for_tuple_field_count_errors;
+
+use declarations_for_tuple_field_count_errors::*;
+
+fn main() {
+    match Z0 {
+        Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+    }
+    match Z1() {
+        Z1 => {} //~ ERROR match bindings cannot shadow tuple structs
+        Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields
+    }
+
+    match S(1, 2, 3) {
+        S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+        S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields
+        S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+        S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+    }
+    match M(1, 2, 3) {
+        M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+        M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields
+        M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+        M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+    }
+
+    match E1::Z0 {
+        E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(x) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+    }
+    match E1::Z1() {
+        E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+        E1::Z1(x) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields
+    }
+    match E1::S(1, 2, 3) {
+        E1::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E1::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E1::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E1::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+
+    match E2::S(1, 2, 3) {
+        E2::S() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E2::S(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E2::S(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E2::S(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+    match E2::M(1, 2, 3) {
+        E2::M() => {} //~ ERROR this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+        E2::M(1) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 3 fields
+        E2::M(xyz, abc) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+        E2::M(1, 2, 3, 4) => {} //~ ERROR this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+    }
+}
diff --git a/src/test/ui/pattern/pat-tuple-field-count-cross.stderr b/src/test/ui/pattern/pat-tuple-field-count-cross.stderr
new file mode 100644 (file)
index 0000000..cab8d47
--- /dev/null
@@ -0,0 +1,536 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/pat-tuple-field-count-cross.rs:13:9
+   |
+LL | use declarations_for_tuple_field_count_errors::*;
+   |     -------------------------------------------- the tuple struct `Z1` is imported here
+...
+LL |         Z1 => {}
+   |         ^^ cannot be named the same as a tuple struct
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:9:9
+   |
+LL |         Z0() => {}
+   |         ^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1
+   |
+LL | pub struct Z0;
+   | -------------- `Z0` defined here
+LL | pub struct Z1();
+   | ---------------- similarly named tuple struct `Z1` defined here
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1() => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:10:9
+   |
+LL |         Z0(x) => {}
+   |         ^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:1:1
+   |
+LL | pub struct Z0;
+   | -------------- `Z0` defined here
+LL | pub struct Z1();
+   | ---------------- similarly named tuple struct `Z1` defined here
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(x) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:31:9
+   |
+LL |         E1::Z0() => {}
+   |         ^^^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- similarly named tuple variant `Z1` defined here
+   |               |
+   |               `E1::Z0` defined here
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1() => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-field-count-cross.rs:32:9
+   |
+LL |         E1::Z0(x) => {}
+   |         ^^^^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:15
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- similarly named tuple variant `Z1` defined here
+   |               |
+   |               `E1::Z0` defined here
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(x) => {}
+   |             ~~
+
+error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+  --> $DIR/pat-tuple-field-count-cross.rs:35:9
+   |
+LL |         E1::Z1 => {}
+   |         ^^^^^^
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |               --  ---- `E1::Z1` defined here
+   |               |
+   |               similarly named unit variant `Z0` defined here
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         E1::Z1(/* fields */) => {}
+   |         ~~~~~~~~~~~~~~~~~~~~
+help: a unit variant with a similar name exists
+   |
+LL |         E1::Z0 => {}
+   |             ~~
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:14:12
+   |
+LL |         Z1(x) => {}
+   |            ^ expected 0 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:2:1
+   |
+LL | pub struct Z1();
+   | ---------------- tuple struct has 0 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:18:9
+   |
+LL |         S() => {}
+   |         ^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(_, _, _) => {}
+   |           +++++++
+help: use `..` to ignore all fields
+   |
+LL |         S(..) => {}
+   |           ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:19:11
+   |
+LL |         S(1) => {}
+   |           ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(1, _, _) => {}
+   |            ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         S(1, ..) => {}
+   |            ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:20:11
+   |
+LL |         S(xyz, abc) => {}
+   |           ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S(xyz, abc, _) => {}
+   |                   +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:21:11
+   |
+LL |         S(1, 2, 3, 4) => {}
+   |           ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:4:14
+   |
+LL | pub struct S(pub u8, pub u8, pub u8);
+   |              ------  ------  ------ tuple struct has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:24:9
+   |
+LL |           M() => {}
+   |           ^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(_, _, _) => {}
+   |           +++++++
+help: use `..` to ignore all fields
+   |
+LL |         M(..) => {}
+   |           ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:25:11
+   |
+LL |           M(1) => {}
+   |             ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(1, _, _) => {}
+   |            ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         M(1, ..) => {}
+   |            ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:26:11
+   |
+LL |           M(xyz, abc) => {}
+   |             ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         M(xyz, abc, _) => {}
+   |                   +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:27:11
+   |
+LL |           M(1, 2, 3, 4) => {}
+   |             ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:5:1
+   |
+LL | / pub struct M(
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------
+LL | |     pub u8,
+   | |     ------ tuple struct has 3 fields
+LL | | );
+   | |__- tuple struct defined here
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:36:16
+   |
+LL |         E1::Z1(x) => {}
+   |                ^ expected 0 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:19
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                   ---- tuple variant has 0 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:39:9
+   |
+LL |         E1::S() => {}
+   |         ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E1::S(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:40:15
+   |
+LL |         E1::S(1) => {}
+   |               ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E1::S(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:41:15
+   |
+LL |         E1::S(xyz, abc) => {}
+   |               ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E1::S(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:42:15
+   |
+LL |         E1::S(1, 2, 3, 4) => {}
+   |               ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:11:27
+   |
+LL | pub enum E1 { Z0, Z1(), S(u8, u8, u8) }
+   |                           --  --  -- tuple variant has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:46:9
+   |
+LL |         E2::S() => {}
+   |         ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E2::S(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:47:15
+   |
+LL |         E2::S(1) => {}
+   |               ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E2::S(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:48:15
+   |
+LL |         E2::S(xyz, abc) => {}
+   |               ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::S(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:49:15
+   |
+LL |         E2::S(1, 2, 3, 4) => {}
+   |               ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:14:7
+   |
+LL |     S(u8, u8, u8),
+   |       --  --  -- tuple variant has 3 fields
+
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:52:9
+   |
+LL |           E2::M() => {}
+   |           ^^^^^^^ expected 3 fields, found 0
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(_, _, _) => {}
+   |               +++++++
+help: use `..` to ignore all fields
+   |
+LL |         E2::M(..) => {}
+   |               ++
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:53:15
+   |
+LL |           E2::M(1) => {}
+   |                 ^ expected 3 fields, found 1
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(1, _, _) => {}
+   |                ++++++
+help: use `..` to ignore the rest of the fields
+   |
+LL |         E2::M(1, ..) => {}
+   |                ++++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:54:15
+   |
+LL |           E2::M(xyz, abc) => {}
+   |                 ^^^  ^^^ expected 3 fields, found 2
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E2::M(xyz, abc, _) => {}
+   |                       +++
+
+error[E0023]: this pattern has 4 fields, but the corresponding tuple variant has 3 fields
+  --> $DIR/pat-tuple-field-count-cross.rs:55:15
+   |
+LL |           E2::M(1, 2, 3, 4) => {}
+   |                 ^  ^  ^  ^ expected 3 fields, found 4
+   |
+  ::: $DIR/auxiliary/declarations-for-tuple-field-count-errors.rs:15:5
+   |
+LL | /     M(
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         --
+LL | |         u8,
+   | |         -- tuple variant has 3 fields
+LL | |     ),
+   | |_____- tuple variant defined here
+
+error: aborting due to 28 previous errors
+
+Some errors have detailed explanations: E0023, E0530, E0532.
+For more information about an error, try `rustc --explain E0023`.
index 46a5e15ffa52cc124a74a1e3868d532d6ac22518..c863c657514f393271655e8165d1826a1039d74c 100644 (file)
@@ -1,4 +1,18 @@
 struct S(u8, u8, u8);
+struct M(
+    u8,
+    u8,
+    u8,
+    u8,
+    u8,
+);
+
+struct Z0;
+struct Z1();
+enum E1 {
+    Z0,
+    Z1(),
+}
 
 fn main() {
     match (1, 2, 3) {
@@ -13,4 +27,48 @@ fn main() {
         //~^ ERROR this pattern has 4 fields, but the corresponding tuple struct has 3 fields
         _ => {}
     }
+    match M(1, 2, 3, 4, 5) {
+        M(1, 2, 3, 4, 5, 6) => {}
+        //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+        M(1,
+          2,
+          3,
+          4,
+          5,
+          6) => {}
+        //~^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+        M(
+            1,
+            2,
+            3,
+            4,
+            5,
+            6,
+        ) => {}
+        //~^^ ERROR this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+    }
+    match Z0 {
+        Z0 => {}
+        Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+        Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit struct `Z0`
+    }
+    match Z1() {
+        Z1 => {} //~ ERROR match bindings cannot shadow tuple structs
+        Z1() => {}
+        Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple struct has 0 fields
+        Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple struct has 0 fields
+    }
+    match E1::Z0 {
+        E1::Z0 => {}
+        E1::Z0() => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(_) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+        E1::Z0(_, _) => {} //~ ERROR expected tuple struct or tuple variant, found unit variant `E1::Z0`
+    }
+    match E1::Z1() {
+        E1::Z1 => {} //~ ERROR expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+        E1::Z1() => {}
+        E1::Z1(_) => {} //~ ERROR this pattern has 1 field, but the corresponding tuple variant has 0 fields
+        E1::Z1(_, _) => {} //~ ERROR this pattern has 2 fields, but the corresponding tuple variant has 0 fields
+    }
 }
index 45b6fd1b4d445e97c662ab9ac0a01ed49072bd25..1c44f7e5f6f1fa8e1015628fc662c57ffa388a10 100644 (file)
@@ -1,5 +1,154 @@
+error[E0530]: match bindings cannot shadow tuple structs
+  --> $DIR/pat-tuple-overfield.rs:57:9
+   |
+LL | struct Z1();
+   | ------------ the tuple struct `Z1` is defined here
+...
+LL |         Z1 => {}
+   |         ^^ cannot be named the same as a tuple struct
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:52:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0() => {}
+   |         ^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1() => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:53:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0(_) => {}
+   |         ^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(_) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit struct `Z0`
+  --> $DIR/pat-tuple-overfield.rs:54:9
+   |
+LL | struct Z0;
+   | ---------- `Z0` defined here
+LL | struct Z1();
+   | ------------ similarly named tuple struct `Z1` defined here
+...
+LL |         Z0(_, _) => {}
+   |         ^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         Z0 => {}
+   |         ~~
+help: a tuple struct with a similar name exists
+   |
+LL |         Z1(_, _) => {}
+   |         ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:64:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0() => {}
+   |         ^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1() => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:65:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0(_) => {}
+   |         ^^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(_) => {}
+   |             ~~
+
+error[E0532]: expected tuple struct or tuple variant, found unit variant `E1::Z0`
+  --> $DIR/pat-tuple-overfield.rs:66:9
+   |
+LL |     Z0,
+   |     -- `E1::Z0` defined here
+LL |     Z1(),
+   |     ---- similarly named tuple variant `Z1` defined here
+...
+LL |         E1::Z0(_, _) => {}
+   |         ^^^^^^^^^^^^
+   |
+help: use this syntax instead
+   |
+LL |         E1::Z0 => {}
+   |         ~~~~~~
+help: a tuple variant with a similar name exists
+   |
+LL |         E1::Z1(_, _) => {}
+   |             ~~
+
+error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E1::Z1`
+  --> $DIR/pat-tuple-overfield.rs:69:9
+   |
+LL |     Z0,
+   |     -- similarly named unit variant `Z0` defined here
+LL |     Z1(),
+   |     ---- `E1::Z1` defined here
+...
+LL |         E1::Z1 => {}
+   |         ^^^^^^
+   |
+help: use the tuple variant pattern syntax instead
+   |
+LL |         E1::Z1() => {}
+   |         ~~~~~~~~
+help: a unit variant with a similar name exists
+   |
+LL |         E1::Z0 => {}
+   |             ~~
+
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-overfield.rs:5:9
+  --> $DIR/pat-tuple-overfield.rs:19:9
    |
 LL |     match (1, 2, 3) {
    |           --------- this expression has type `({integer}, {integer}, {integer})`
@@ -10,7 +159,7 @@ LL |         (1, 2, 3, 4) => {}
               found tuple `(_, _, _, _)`
 
 error[E0308]: mismatched types
-  --> $DIR/pat-tuple-overfield.rs:6:9
+  --> $DIR/pat-tuple-overfield.rs:20:9
    |
 LL |     match (1, 2, 3) {
    |           --------- this expression has type `({integer}, {integer}, {integer})`
@@ -22,24 +171,139 @@ LL |         (1, 2, .., 3, 4) => {}
               found tuple `(_, _, _, _)`
 
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/pat-tuple-overfield.rs:10:9
+  --> $DIR/pat-tuple-overfield.rs:24:11
    |
 LL | struct S(u8, u8, u8);
-   | --------------------- tuple struct defined here
+   |          --  --  -- tuple struct has 3 fields
 ...
 LL |         S(1, 2, 3, 4) => {}
-   |         ^^^^^^^^^^^^^ expected 3 fields, found 4
+   |           ^  ^  ^  ^ expected 3 fields, found 4
 
 error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
-  --> $DIR/pat-tuple-overfield.rs:12:9
+  --> $DIR/pat-tuple-overfield.rs:26:11
    |
 LL | struct S(u8, u8, u8);
-   | --------------------- tuple struct defined here
+   |          --  --  -- tuple struct has 3 fields
 ...
 LL |         S(1, 2, .., 3, 4) => {}
-   |         ^^^^^^^^^^^^^^^^^ expected 3 fields, found 4
+   |           ^  ^      ^  ^ expected 3 fields, found 4
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:31:11
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(1, 2, 3, 4, 5, 6) => {}
+   |           ^  ^  ^  ^  ^  ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:33:11
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(1,
+   |         - ^
+LL |           2,
+   |           ^
+LL |           3,
+   |           ^
+LL |           4,
+   |           ^
+LL |           5,
+   |           ^
+LL |           6) => {}
+   |           ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 6 fields, but the corresponding tuple struct has 5 fields
+  --> $DIR/pat-tuple-overfield.rs:41:13
+   |
+LL | struct M(
+   |        - tuple struct defined here
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     --
+LL |     u8,
+   |     -- tuple struct has 5 fields
+...
+LL |         M(
+   |         -
+LL |             1,
+   |             ^
+LL |             2,
+   |             ^
+LL |             3,
+   |             ^
+LL |             4,
+   |             ^
+LL |             5,
+   |             ^
+LL |             6,
+   |             ^ expected 5 fields, found 6
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:59:12
+   |
+LL | struct Z1();
+   | ------------ tuple struct has 0 fields
+...
+LL |         Z1(_) => {}
+   |            ^ expected 0 fields, found 1
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:60:12
+   |
+LL | struct Z1();
+   | ------------ tuple struct has 0 fields
+...
+LL |         Z1(_, _) => {}
+   |            ^  ^ expected 0 fields, found 2
+
+error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:71:16
+   |
+LL |     Z1(),
+   |     ---- tuple variant has 0 fields
+...
+LL |         E1::Z1(_) => {}
+   |                ^ expected 0 fields, found 1
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 0 fields
+  --> $DIR/pat-tuple-overfield.rs:72:16
+   |
+LL |     Z1(),
+   |     ---- tuple variant has 0 fields
+...
+LL |         E1::Z1(_, _) => {}
+   |                ^  ^ expected 0 fields, found 2
 
-error: aborting due to 4 previous errors
+error: aborting due to 19 previous errors
 
-Some errors have detailed explanations: E0023, E0308.
+Some errors have detailed explanations: E0023, E0308, E0530, E0532.
 For more information about an error, try `rustc --explain E0023`.
index ed852a47bb4ee1752ea520fe2c24be41c796b7a8..dac60e3fab2c0038e2d617007f80bf23b65c4c86 100644 (file)
@@ -21,6 +21,12 @@ fn main() {
         //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
         //~| HELP use `_` to explicitly ignore each field
         //~| HELP use `..` to ignore all fields
+
+        // Test non-standard formatting
+        S () => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
     }
 
     match E::S(0, 1.0) {
@@ -39,6 +45,12 @@ fn main() {
         //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
         //~| HELP use `_` to explicitly ignore each field
         //~| HELP use `..` to ignore all fields
+
+        // Test non-standard formatting
+        E::S () => {}
+        //~^ ERROR this pattern has 0 fields, but the corresponding tuple variant has 2 fields
+        //~| HELP use `_` to explicitly ignore each field
+        //~| HELP use `..` to ignore all fields
     }
     match E::S(0, 1.0) {
         E::S => {}
index 2fbcb6d67ba3634da5a33fb874ec5f774b959bde..e75f9b38da56640a90e20896aee3f6dafd4b26a6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0532]: expected unit struct, unit variant or constant, found tuple variant `E::S`
-  --> $DIR/pat-tuple-underfield.rs:44:9
+  --> $DIR/pat-tuple-underfield.rs:56:9
    |
 LL |     S(i32, f32),
    |     ----------- `E::S` defined here
@@ -8,13 +8,13 @@ LL |         E::S => {}
    |         ^^^^ help: use the tuple variant pattern syntax instead: `E::S(_, _)`
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:9:9
+  --> $DIR/pat-tuple-underfield.rs:9:11
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S(x) => {}
-   |         ^^^^ expected 2 fields, found 1
+   |           ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -22,13 +22,13 @@ LL |         S(x, _) => {}
    |            +++
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:14:9
+  --> $DIR/pat-tuple-underfield.rs:14:11
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S(_) => {}
-   |         ^^^^ expected 2 fields, found 1
+   |           ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -43,7 +43,7 @@ error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has
   --> $DIR/pat-tuple-underfield.rs:20:9
    |
 LL | struct S(i32, f32);
-   | ------------------- tuple struct defined here
+   |          ---  --- tuple struct has 2 fields
 ...
 LL |         S() => {}
    |         ^^^ expected 2 fields, found 0
@@ -57,14 +57,32 @@ help: use `..` to ignore all fields
 LL |         S(..) => {}
    |           ++
 
+error[E0023]: this pattern has 0 fields, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-tuple-underfield.rs:26:9
+   |
+LL | struct S(i32, f32);
+   |          ---  --- tuple struct has 2 fields
+...
+LL |         S () => {}
+   |         ^^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         S (_, _) => {}
+   |            ++++
+help: use `..` to ignore all fields
+   |
+LL |         S (..) => {}
+   |            ++
+
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:27:9
+  --> $DIR/pat-tuple-underfield.rs:33:14
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S(x) => {}
-   |         ^^^^^^^ expected 2 fields, found 1
+   |              ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -72,13 +90,13 @@ LL |         E::S(x, _) => {}
    |               +++
 
 error[E0023]: this pattern has 1 field, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:32:9
+  --> $DIR/pat-tuple-underfield.rs:38:14
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S(_) => {}
-   |         ^^^^^^^ expected 2 fields, found 1
+   |              ^ expected 2 fields, found 1
    |
 help: use `_` to explicitly ignore each field
    |
@@ -90,10 +108,10 @@ LL |         E::S(..) => {}
    |              ~~
 
 error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/pat-tuple-underfield.rs:38:9
+  --> $DIR/pat-tuple-underfield.rs:44:9
    |
 LL |     S(i32, f32),
-   |     ----------- tuple variant defined here
+   |       ---  --- tuple variant has 2 fields
 ...
 LL |         E::S() => {}
    |         ^^^^^^ expected 2 fields, found 0
@@ -107,14 +125,32 @@ help: use `..` to ignore all fields
 LL |         E::S(..) => {}
    |              ++
 
-error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 2 fields
   --> $DIR/pat-tuple-underfield.rs:50:9
    |
+LL |     S(i32, f32),
+   |       ---  --- tuple variant has 2 fields
+...
+LL |         E::S () => {}
+   |         ^^^^^^^ expected 2 fields, found 0
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |         E::S (_, _) => {}
+   |               ++++
+help: use `..` to ignore all fields
+   |
+LL |         E::S (..) => {}
+   |               ++
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 4 fields
+  --> $DIR/pat-tuple-underfield.rs:62:19
+   |
 LL | struct Point4(i32, i32, i32, i32);
-   | ---------------------------------- tuple struct defined here
+   |               ---  ---  ---  --- tuple struct has 4 fields
 ...
 LL |         Point4(   a   ,     _    ) => {}
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 4 fields, found 2
+   |                   ^         ^ expected 4 fields, found 2
    |
 help: use `_` to explicitly ignore each field
    |
@@ -125,7 +161,7 @@ help: use `..` to ignore the rest of the fields
 LL |         Point4(   a, ..) => {}
    |                    ~~~~
 
-error: aborting due to 8 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0023, E0532.
 For more information about an error, try `rustc --explain E0023`.
index 3f28ffed291629bf659a68eb7af2ac028c827c2f..c800afdae2afb4ef205fbfdce14a090139c75504 100644 (file)
@@ -26,13 +26,13 @@ LL |         A::B(_) => (),
    |            ~
 
 error[E0023]: this pattern has 3 fields, but the corresponding tuple variant has 2 fields
-  --> $DIR/pattern-error-continue.rs:17:9
+  --> $DIR/pattern-error-continue.rs:17:14
    |
 LL |     B(isize, isize),
-   |     --------------- tuple variant defined here
+   |       -----  ----- tuple variant has 2 fields
 ...
 LL |         A::B(_, _, _) => (),
-   |         ^^^^^^^^^^^^^ expected 2 fields, found 3
+   |              ^  ^  ^ expected 2 fields, found 3
 
 error[E0308]: mismatched types
   --> $DIR/pattern-error-continue.rs:22:9
index 7549eae7016b56844c89fde92fffafb06de1d8a8..c85af7f3bcc79bcbf86b350857ee54023074ea8a 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 #![deny(irrefutable_let_patterns)]
 
index 0caa79a91529d14d7deacd340a92b8d0e1ef1d81..b97683526bac370556767a1e67e196f8bad4a02f 100644 (file)
@@ -1,11 +1,11 @@
 error: irrefutable `if let` pattern
-  --> $DIR/deny-irrefutable-let-patterns.rs:7:8
+  --> $DIR/deny-irrefutable-let-patterns.rs:6:8
    |
 LL |     if let _ = 5 {}
    |        ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/deny-irrefutable-let-patterns.rs:4:9
+  --> $DIR/deny-irrefutable-let-patterns.rs:3:9
    |
 LL | #![deny(irrefutable_let_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL | #![deny(irrefutable_let_patterns)]
    = help: consider replacing the `if let` with a `let`
 
 error: irrefutable `while let` pattern
-  --> $DIR/deny-irrefutable-let-patterns.rs:9:11
+  --> $DIR/deny-irrefutable-let-patterns.rs:8:11
    |
 LL |     while let _ = 5 {
    |           ^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     while let _ = 5 {
    = help: consider instead using a `loop { ... }` with a `let` inside it
 
 error: irrefutable `if let` guard pattern
-  --> $DIR/deny-irrefutable-let-patterns.rs:14:18
+  --> $DIR/deny-irrefutable-let-patterns.rs:13:18
    |
 LL |         _ if let _ = 2 => {}
    |                  ^
index 4b47b978930f30c6e6c21d2f734ccf35296fb912..076de846129e676b51b742fbe1b8ed0c1c09f51a 100644 (file)
@@ -1,3 +1,5 @@
+#![feature(let_else)]
+
 #![deny(unreachable_patterns)]
 
 fn main() {
@@ -53,4 +55,5 @@ fn main() {
         1..=2 => {}, //~ ERROR unreachable pattern
         _ => {},
     }
+    let (0 | 0) = 0 else { return }; //~ ERROR unreachable pattern
 }
index 76bc4f8d0910adf2526453c686d33a0f6ab56db6..dd5936fdcc42930c9ca3afb2d1a29153377b0424 100644 (file)
@@ -1,68 +1,74 @@
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:4:23
+  --> $DIR/top-level-alternation.rs:6:23
    |
 LL |     while let 0..=2 | 1 = 0 {}
    |                       ^
    |
 note: the lint level is defined here
-  --> $DIR/top-level-alternation.rs:1:9
+  --> $DIR/top-level-alternation.rs:3:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:5:20
+  --> $DIR/top-level-alternation.rs:7:20
    |
 LL |     if let 0..=2 | 1 = 0 {}
    |                    ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:9:15
+  --> $DIR/top-level-alternation.rs:11:15
    |
 LL |             | 0 => {}
    |               ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:14:15
+  --> $DIR/top-level-alternation.rs:16:15
    |
 LL |             | Some(0) => {}
    |               ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:19:9
+  --> $DIR/top-level-alternation.rs:21:9
    |
 LL |         (0, 0) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:39:9
+  --> $DIR/top-level-alternation.rs:41:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:43:9
+  --> $DIR/top-level-alternation.rs:45:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:44:9
+  --> $DIR/top-level-alternation.rs:46:9
    |
 LL |         None => {}
    |         ^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:49:9
+  --> $DIR/top-level-alternation.rs:51:9
    |
 LL |         None | Some(_) => {}
    |         ^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:53:9
+  --> $DIR/top-level-alternation.rs:55:9
    |
 LL |         1..=2 => {},
    |         ^^^^^
 
-error: aborting due to 10 previous errors
+error: unreachable pattern
+  --> $DIR/top-level-alternation.rs:58:14
+   |
+LL |     let (0 | 0) = 0 else { return };
+   |              ^
+
+error: aborting due to 11 previous errors
 
index f20605e1b9a610c02f35838c0764ac58c3e6ffda..2f41beeb9691a36b82db1e849e7fc010019308ea 100644 (file)
@@ -1,7 +1,7 @@
 // build-fail
 // compile-flags:-Zpolymorphize=on
-#![feature(const_generics, rustc_attrs)]
-//~^ WARN the feature `const_generics` is incomplete
+#![feature(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` is incomplete
 
 // This test checks that the polymorphization analysis correctly detects unused const
 // parameters in closures.
index 266b6e62afd0bf930050b14dd4ac72f5e5763237..d0ee89329965291ef47f8778e0d6b8c73bb247cf 100644 (file)
@@ -1,11 +1,11 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/closures.rs:3:12
    |
-LL | #![feature(const_generics, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
   --> $DIR/closures.rs:19:19
index 04c279de29e6ac5ae9485c40a231d71b003e03ec..cbc1b63fbc4e6d19dfea0e49846359afe235f5dc 100644 (file)
@@ -1,7 +1,7 @@
 // build-fail
 // compile-flags:-Zpolymorphize=on
-#![feature(const_generics, rustc_attrs)]
-//~^ WARN the feature `const_generics` is incomplete
+#![feature(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` is incomplete
 
 // This test checks that the polymorphization analysis correctly detects unused const
 // parameters in functions.
index e379e32c1fceb11cbc9ef4e4a6e259f5da0b80f2..03d0bbb6afe60b46cba4a0a72ac7ff30a08c8701 100644 (file)
@@ -1,11 +1,11 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/functions.rs:3:12
    |
-LL | #![feature(const_generics, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
   --> $DIR/functions.rs:15:8
index 9eb34fb73490b8585d9d4c4bf458e61e0b7ae964..f295cf15d08c6005d850282b4ce3c36b790942f2 100644 (file)
@@ -1,7 +1,7 @@
 // build-fail
 // compile-flags:-Zpolymorphize=on
-#![feature(const_generics, generators, generator_trait, rustc_attrs)]
-//~^ WARN the feature `const_generics` is incomplete
+#![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` is incomplete
 
 use std::marker::Unpin;
 use std::ops::{Generator, GeneratorState};
index c59055ba9d65473ff191d5463825056a64bde007..c4e566a42d0cf53db6b4b69cdbaae952ab6da273 100644 (file)
@@ -1,11 +1,11 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/generators.rs:3:12
    |
-LL | #![feature(const_generics, generators, generator_trait, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
   --> $DIR/generators.rs:36:5
index 2831f861f556167dd2e0a782596305908875793b..d2d0f33681244a896768027c998c5939b517d64d 100644 (file)
@@ -1,8 +1,8 @@
 // build-fail
 // compile-flags:-Zpolymorphize=on
 #![crate_type = "lib"]
-#![feature(lazy_normalization_consts, rustc_attrs)]
-//~^ WARN the feature `lazy_normalization_consts` is incomplete
+#![feature(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` is incomplete
 
 #[rustc_polymorphize_error]
 fn test<T>() {
index 38d4808c48c03f63f814ae7e7c1883ed40d6bca2..4d7bab6aaa0c6407a1458d3f631cd798da37167e 100644 (file)
@@ -1,11 +1,11 @@
-warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/promoted-function-2.rs:4:12
    |
-LL | #![feature(lazy_normalization_consts, rustc_attrs)]
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+   |            ^^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #72219 <https://github.com/rust-lang/rust/issues/72219> for more information
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
 
 error: item has unused generic parameters
   --> $DIR/promoted-function-2.rs:8:4
index 7f3a7e670b9b75b8c5727f55502d9b03c985a8a1..127c49957c1e55b3032a14cc937d70113c57370c 100644 (file)
@@ -1,3 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/attribute-with-error.rs:25:22
+   |
+LL |         let a: i32 = "foo";
+   |                ---   ^^^^^ expected `i32`, found `&str`
+   |                |
+   |                expected due to this
+
 error[E0308]: mismatched types
   --> $DIR/attribute-with-error.rs:10:18
    |
@@ -14,14 +22,6 @@ LL |     let b: i32 = "f'oo";
    |            |
    |            expected due to this
 
-error[E0308]: mismatched types
-  --> $DIR/attribute-with-error.rs:25:22
-   |
-LL |         let a: i32 = "foo";
-   |                ---   ^^^^^ expected `i32`, found `&str`
-   |                |
-   |                expected due to this
-
 error[E0308]: mismatched types
   --> $DIR/attribute-with-error.rs:35:22
    |
index 4f11f81b00bfab4b294036b46f8a720824a7907a..8c1a9dc80265e17e87eb0b3be1f707ce43592649 100644 (file)
@@ -1,12 +1,19 @@
 // Test proc-macro crate can be built without additional RUSTFLAGS
 // on musl target
 // override -Ctarget-feature=-crt-static from compiletest
-// compile-flags: -Ctarget-feature=
+// compile-flags: --crate-type proc-macro -Ctarget-feature=
 // ignore-wasm32
 // ignore-sgx no support for proc-macro crate type
 // build-pass
 #![crate_type = "proc-macro"]
 
+// FIXME: This don't work when crate-type is specified by attribute
+// `#![crate_type = "proc-macro"]`, not by `--crate-type=proc-macro`
+// command line flag. This is beacuse the list of `cfg` symbols is generated
+// before attributes are parsed. See rustc_interface::util::add_configuration
+#[cfg(target_feature = "crt-static")]
+compile_error!("crt-static is enabled");
+
 extern crate proc_macro;
 
 use proc_macro::TokenStream;
diff --git a/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed b/src/test/ui/proc-macro/issue-86781-bad-inner-doc.fixed
new file mode 100644 (file)
index 0000000..426a5fa
--- /dev/null
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+// run-rustfix
+
+#[macro_use]
+extern crate test_macros;
+
+/// Inner doc comment
+//~^ ERROR expected outer doc comment
+#[derive(Empty)]
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
+
+fn main() {}
index 8be1ae77738e9cdc2d8dc6703c021e728fe8f38d..31e3f3c859236718060cd339080330d95c4b7b20 100644 (file)
@@ -1,4 +1,5 @@
 // aux-build:test-macros.rs
+// run-rustfix
 
 #[macro_use]
 extern crate test_macros;
@@ -6,6 +7,6 @@
 //! Inner doc comment
 //~^ ERROR expected outer doc comment
 #[derive(Empty)]
-pub struct Foo;
+pub struct Foo; //~ NOTE the inner doc comment doesn't annotate this struct
 
 fn main() {}
index 0b2e612ee5bb96b18803c75d4855aa77002da3d6..a92f07522e5f21e04b20e3ef9a64a7a9cd69be49 100644 (file)
@@ -1,10 +1,16 @@
 error[E0753]: expected outer doc comment
-  --> $DIR/issue-86781-bad-inner-doc.rs:6:1
+  --> $DIR/issue-86781-bad-inner-doc.rs:7:1
    |
 LL | //! Inner doc comment
    | ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | pub struct Foo;
+   | --------------- the inner doc comment doesn't annotate this struct
    |
-   = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+help: to annotate the struct, change the doc comment from inner to outer style
+   |
+LL | /// Inner doc comment
+   |   ~
 
 error: aborting due to previous error
 
index 4d1cd059c27b5e64e5072f33f2e3b920ba1687b7..03cb3e24b7dbff0c49ca7c063aa2370779e8deda 100644 (file)
@@ -1,6 +1,8 @@
-//~ ERROR cycle detected when computing layout of
-//~| NOTE ...which requires computing layout of
-//~| NOTE ...which again requires computing layout of
+//~ ERROR cycle detected when computing layout of `S`
+//~| NOTE ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
+//~| NOTE ...which requires computing layout of `std::option::Option<S>`...
+//~| NOTE ...which again requires computing layout of `S`, completing the cycle
+//~| NOTE cycle used when computing layout of `std::option::Option<S>`
 
 // build-fail
 
@@ -13,6 +15,5 @@ impl<T: ?Sized> Mirror for T {
 struct S(Option<<S as Mirror>::It>);
 
 fn main() {
-    //~^ NOTE cycle used when optimizing MIR for `main`
     let _s = S(None);
 }
index be55890c08c88598619337f96ed63a1f557e24db..21c0e1e6de5f34b05f0704995dbda5d3e1d6ce88 100644 (file)
@@ -1,12 +1,9 @@
-error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
+error[E0391]: cycle detected when computing layout of `S`
    |
-   = note: ...which requires computing layout of `S`...
-   = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
-note: cycle used when optimizing MIR for `main`
-  --> $DIR/issue-26548-recursion-via-normalize.rs:15:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
+   = note: ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
+   = note: ...which requires computing layout of `std::option::Option<S>`...
+   = note: ...which again requires computing layout of `S`, completing the cycle
+   = note: cycle used when computing layout of `std::option::Option<S>`
 
 error: aborting due to previous error
 
index a4272802af54d0ee453b0e2e6a260ce405d5da5a..c1dab6086ef3a97c2c35c26ce40df9d25aadc6eb 100644 (file)
@@ -19,7 +19,7 @@ trait Trait2<'a, 'b> {
 // since for it to be WF, we would need to know that `'y: 'x`, but we
 // do not infer that.
 fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-    //~^ ERROR reference has a longer lifetime than the data it references
+    //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
 {
 }
 
index 6470ebf541b5b9096416fb1ae66c91a06d53a088..44ef13c740c061ba150e5659ed4b4fc7971da33e 100644 (file)
@@ -1,20 +1,14 @@
-error[E0491]: in type `&'x (dyn for<'z> Trait1<<T as Trait2<'y, 'z>>::Foo> + 'x)`, reference has a longer lifetime than the data it references
-  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:25
+error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:4
    |
 LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |    ^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
    |
-note: the pointer is valid for the lifetime `'x` as defined on the function body at 21:11
-  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11
+help: consider restricting type parameter `T`
    |
-LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-   |           ^^
-note: but the referenced data is only valid for the lifetime `'y` as defined on the function body at 21:15
-  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15
-   |
-LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-   |               ^^
+LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |                    ++++++++++++++++++++++++
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0491`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/remap-path-prefix.rs b/src/test/ui/remap-path-prefix.rs
new file mode 100644 (file)
index 0000000..2eef970
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: --remap-path-prefix={{src-base}}=remapped
+
+fn main() {
+    // We cannot actually put an ERROR marker here because
+    // the file name in the error message is not what the
+    // test framework expects (since the filename gets remapped).
+    // We still test the expected error in the stderr file.
+    ferris
+}
diff --git a/src/test/ui/remap-path-prefix.stderr b/src/test/ui/remap-path-prefix.stderr
new file mode 100644 (file)
index 0000000..ad6a35d
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `ferris` in this scope
+  --> remapped/remap-path-prefix.rs:8:5
+   |
+LL |     ferris
+   |     ^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
index cd07e5b8935f201cb0418b0b45fbc2ee28e27003..c85f057203146ffdc52157e9f903a196c862a5f2 100644 (file)
@@ -30,12 +30,6 @@ error[E0308]: mismatched types
 LL |     let e = [0; "foo"];
    |                 ^^^^^ expected `usize`, found `&str`
 
-error[E0308]: mismatched types
-  --> $DIR/repeat_count.rs:31:17
-   |
-LL |     let g = [0; G { g: () }];
-   |                 ^^^^^^^^^^^ expected `usize`, found struct `G`
-
 error[E0308]: mismatched types
   --> $DIR/repeat_count.rs:19:17
    |
@@ -63,6 +57,12 @@ help: change the type of the numeric literal from `u8` to `usize`
 LL |     let f = [0; 4usize];
    |                 ~~~~~~
 
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:31:17
+   |
+LL |     let g = [0; G { g: () }];
+   |                 ^^^^^^^^^^^ expected `usize`, found struct `G`
+
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0308, E0435.
index 525b5cf7d8417f7d04573522598d4ca2ef6c65f9..0dcf0184db107005eea351fffa5a01fb6408d08d 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing type of `<impl at $DIR/issue-23305.r
 LL | impl dyn ToNbt<Self> {}
    |                ^^^^
    |
-   = note: ...which again requires computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:24>`, completing the cycle
+   = note: ...which immediately requires computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:24>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/issue-23305.rs:1:1
    |
index f09ab3bf919881a2053fa05b0feadfc3d3d880f8..f96c04841dd286eb9c387291c2bbdcf0ce14146a 100644 (file)
@@ -1,6 +1,3 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
-
 fn f<T>() {
     extern "C" {
         static a: *const T;
index 7f8151db06f5b8a8ca55699fc564754c6f35465d..7ed572f80b896887b32edec9ff8728338043ecce 100644 (file)
@@ -1,5 +1,5 @@
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-65035-static-with-parent-generics.rs:6:26
+  --> $DIR/issue-65035-static-with-parent-generics.rs:3:26
    |
 LL | fn f<T>() {
    |      - type parameter from outer function
@@ -8,7 +8,7 @@ LL |         static a: *const T;
    |                          ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-65035-static-with-parent-generics.rs:12:22
+  --> $DIR/issue-65035-static-with-parent-generics.rs:9:22
    |
 LL | fn g<T: Default>() {
    |      - type parameter from outer function
@@ -16,7 +16,7 @@ LL |     static a: *const T = Default::default();
    |                      ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-65035-static-with-parent-generics.rs:18:24
+  --> $DIR/issue-65035-static-with-parent-generics.rs:15:24
    |
 LL | fn h<const N: usize>() {
    |            - const parameter from outer function
@@ -25,7 +25,7 @@ LL |         static a: [u8; N];
    |                        ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-65035-static-with-parent-generics.rs:24:20
+  --> $DIR/issue-65035-static-with-parent-generics.rs:21:20
    |
 LL | fn i<const N: usize>() {
    |            - const parameter from outer function
@@ -33,22 +33,13 @@ LL |     static a: [u8; N] = [0; N];
    |                    ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/issue-65035-static-with-parent-generics.rs:24:29
+  --> $DIR/issue-65035-static-with-parent-generics.rs:21:29
    |
 LL | fn i<const N: usize>() {
    |            - const parameter from outer function
 LL |     static a: [u8; N] = [0; N];
    |                             ^ use of generic parameter from outer function
 
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-65035-static-with-parent-generics.rs:1:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 5 previous errors; 1 warning emitted
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0401`.
index 5b5c1834cad1954c65d3ba0146726091b2eaafd1..7f623e47353b93844e778705354cfd6ac99bc1bf 100644 (file)
@@ -4,7 +4,7 @@ error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-
 LL | impl Tr for Self {}
    |             ^^^^
    |
-   = note: ...which again requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>`, completing the cycle
+   = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:20>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/resolve-self-in-impl.rs:1:1
    |
@@ -23,7 +23,7 @@ error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-
 LL | impl Tr for S<Self> {}
    |               ^^^^
    |
-   = note: ...which again requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>`, completing the cycle
+   = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:23>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/resolve-self-in-impl.rs:1:1
    |
@@ -42,7 +42,7 @@ error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-
 LL | impl Self {}
    |      ^^^^
    |
-   = note: ...which again requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>`, completing the cycle
+   = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:13>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/resolve-self-in-impl.rs:1:1
    |
@@ -61,7 +61,7 @@ error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-
 LL | impl S<Self> {}
    |        ^^^^
    |
-   = note: ...which again requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>`, completing the cycle
+   = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:16>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/resolve-self-in-impl.rs:1:1
    |
@@ -80,7 +80,7 @@ error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/
 LL | impl Tr<Self::A> for S {}
    | ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which again requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>`, completing the cycle
+   = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:26>` again
 note: cycle used when collecting item types in top-level module
   --> $DIR/resolve-self-in-impl.rs:1:1
    |
index 4014af2f41b61a1956294f13b6ca3d4dc10025b7..cca9f2dc88ca0d8dcda92a045274db8c481792e7 100644 (file)
@@ -1,8 +1,8 @@
 error: mismatched closing delimiter: `)`
-  --> $DIR/token-error-correct-2.rs:6:5
+  --> $DIR/token-error-correct-2.rs:4:12
    |
 LL |     if foo {
-   |            - unclosed delimiter
+   |            ^ unclosed delimiter
 LL |
 LL |     )
    |     ^ mismatched closing delimiter
index 31087e394adfe4a6fef782ba219fc8ca2b9e03d2..77c87c78466b1d68faeff1f74615c3fa459c5b2b 100644 (file)
@@ -1,8 +1,8 @@
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-3.rs:13:35
+  --> $DIR/token-error-correct-3.rs:13:21
    |
 LL |             callback(path.as_ref();
-   |                     -             ^ help: `)` may belong here
+   |                     ^             ^ help: `)` may belong here
    |                     |
    |                     unclosed delimiter
 
index 64aff54ba731128370867ce82a5a947daa6064e2..81e5a133691595f259080f77d4d75be661f82a55 100644 (file)
@@ -1,8 +1,8 @@
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-4.rs:9:21
+  --> $DIR/token-error-correct-4.rs:9:12
    |
 LL |     setsuna(kazusa();
-   |            -        ^ help: `)` may belong here
+   |            ^        ^ help: `)` may belong here
    |            |
    |            unclosed delimiter
 
index bf300ecd781733b4020b65baae83f698ecf345c3..ca0c4c18ad4baf1b4497dc09a8a14726885bbc5b 100644 (file)
@@ -1,10 +1,10 @@
 error: mismatched closing delimiter: `}`
-  --> $DIR/token-error-correct.rs:6:1
+  --> $DIR/token-error-correct.rs:4:12
    |
 LL | fn main() {
    |           - closing delimiter possibly meant for this
 LL |     foo(bar(;
-   |            - unclosed delimiter
+   |            ^ unclosed delimiter
 LL |
 LL | }
    | ^ mismatched closing delimiter
index 00dcf89c7aa674a2d3a2b1c416e870980b30150f..2ad92b79444925ac56ba7d8affbb050b64d17a72 100644 (file)
@@ -10,8 +10,8 @@ fn main() {
     let mut x = NonExhaustiveMonovariant::Variant(1);
     let y = &mut x;
     match x {
-        NonExhaustiveMonovariant::Variant(_) => {},
         //~^ ERROR cannot use `x` because it was mutably borrowed
+        NonExhaustiveMonovariant::Variant(_) => {},
         _ => {},
     }
     drop(y);
index 9edfa84cbc0852c4854e1cf08f1777c33a0efc68..de730ce1030f24bbab5699e3a644dc2acce470a5 100644 (file)
@@ -1,11 +1,10 @@
 error[E0503]: cannot use `x` because it was mutably borrowed
-  --> $DIR/borrowck-non-exhaustive.rs:13:9
+  --> $DIR/borrowck-non-exhaustive.rs:12:11
    |
 LL |     let y = &mut x;
    |             ------ borrow of `x` occurs here
 LL |     match x {
-LL |         NonExhaustiveMonovariant::Variant(_) => {},
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of borrowed `x`
+   |           ^ use of borrowed `x`
 ...
 LL |     drop(y);
    |          - borrow later used here
index 4e2d70e3290ec44f0c5c53ff3a52400975b82ce4..1f32e4af121f2b240c496cea98272fd2f9c9ed4d 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 fn main() {
     match Some(None) {
index 9c5d92a33ada725771dd41ba5c11405e0ec44926..2463b7f3eacc7eb543c41c89c9af226e86b9d1bf 100644 (file)
@@ -1,11 +1,11 @@
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/bindings.rs:7:14
+  --> $DIR/bindings.rs:6:14
    |
 LL |         _ => y,
    |              ^ not found in this scope
 
 error[E0425]: cannot find value `y` in this scope
-  --> $DIR/bindings.rs:9:5
+  --> $DIR/bindings.rs:8:5
    |
 LL |     y
    |     ^ not found in this scope
index a3663003790f7eeda51368eaddfe0076edf44dc0..3da57989df2b5820db159081b68af6c9cf7e22e5 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
 
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 enum Foo {
     Bar,
index a4fc7f8cf2b263a4fff22f6824af6eab4402b2b6..ad178dfa43947b1c4d682721b6c7dd24df94fa0e 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 fn ok() -> Result<Option<bool>, ()> {
     Ok(Some(true))
index 6407128d8d8773dc852f896b575a1d3bc8e22a9a..fbb941ffd9102ea427646a9ae47f95d654c22398 100644 (file)
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/typeck.rs:10:22
+  --> $DIR/typeck.rs:9:22
    |
 LL |         Ok(x) if let Err(_) = x => {},
    |                      ^^^^^^ expected enum `Option`, found enum `Result`
@@ -8,7 +8,7 @@ LL |         Ok(x) if let Err(_) = x => {},
               found enum `Result<_, _>`
 
 error[E0308]: mismatched types
-  --> $DIR/typeck.rs:12:22
+  --> $DIR/typeck.rs:11:22
    |
 LL |         Ok(x) if let 0 = x => {},
    |                      ^ expected enum `Option`, found integer
index d921367b91775f3c114471e5e16b170f1025d0f4..3ad1a50c61f83194efa915efb98a486af794d1bc 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(if_let_guard)]
-#![allow(incomplete_features)]
 
 #[deny(irrefutable_let_patterns)]
 fn irrefutable_let_guard() {
index c7627f1c3c50c1c6c100d381cbb8a47c656a0926..cf64513f9c81baa2a3e91fe3ed522a0ab5d5553e 100644 (file)
@@ -1,11 +1,11 @@
 error: irrefutable `if let` guard pattern
-  --> $DIR/warns.rs:7:24
+  --> $DIR/warns.rs:6:24
    |
 LL |         Some(x) if let () = x => {}
    |                        ^^
    |
 note: the lint level is defined here
-  --> $DIR/warns.rs:4:8
+  --> $DIR/warns.rs:3:8
    |
 LL | #[deny(irrefutable_let_patterns)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -13,13 +13,13 @@ LL | #[deny(irrefutable_let_patterns)]
    = help: consider removing the guard and adding a `let` inside the match arm
 
 error: unreachable pattern
-  --> $DIR/warns.rs:16:25
+  --> $DIR/warns.rs:15:25
    |
 LL |         x if let None | None = x => {}
    |                         ^^^^
    |
 note: the lint level is defined here
-  --> $DIR/warns.rs:13:8
+  --> $DIR/warns.rs:12:8
    |
 LL | #[deny(unreachable_patterns)]
    |        ^^^^^^^^^^^^^^^^^^^^
index b3c9246486ebb375f1aa3c98674d03b8319febd9..b0b3464c61017b4cadf9717fdef21f40a510194d 100644 (file)
@@ -17,8 +17,6 @@
 //
 // To that end, we check some positions which is not part of the language above.
 
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
 #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test.
 //~^ WARN the feature `let_chains` is incomplete
 
index b48915adc683bddef124a38e552b17a9378e5ecb..5ec4352919ea015c2c78c9bf0f835e88dce2db2f 100644 (file)
@@ -1,5 +1,5 @@
 error: expressions must be enclosed in braces to be used as const generic arguments
-  --> $DIR/disallowed-positions.rs:235:9
+  --> $DIR/disallowed-positions.rs:233:9
    |
 LL |         true && let 1 = 1
    |         ^^^^^^^^^^^^^^^^^
@@ -10,7 +10,7 @@ LL |         { true && let 1 = 1 }
    |         +                   +
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:32:9
+  --> $DIR/disallowed-positions.rs:30:9
    |
 LL |     if &let 0 = 0 {}
    |         ^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     if &let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:35:9
+  --> $DIR/disallowed-positions.rs:33:9
    |
 LL |     if !let 0 = 0 {}
    |         ^^^^^^^^^
@@ -28,7 +28,7 @@ LL |     if !let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:36:9
+  --> $DIR/disallowed-positions.rs:34:9
    |
 LL |     if *let 0 = 0 {}
    |         ^^^^^^^^^
@@ -37,7 +37,7 @@ LL |     if *let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:38:9
+  --> $DIR/disallowed-positions.rs:36:9
    |
 LL |     if -let 0 = 0 {}
    |         ^^^^^^^^^
@@ -46,7 +46,7 @@ LL |     if -let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:46:9
+  --> $DIR/disallowed-positions.rs:44:9
    |
 LL |     if (let 0 = 0)? {}
    |         ^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     if (let 0 = 0)? {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:50:16
+  --> $DIR/disallowed-positions.rs:48:16
    |
 LL |     if true || let 0 = 0 {}
    |                ^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     if true || let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:51:17
+  --> $DIR/disallowed-positions.rs:49:17
    |
 LL |     if (true || let 0 = 0) {}
    |                 ^^^^^^^^^
@@ -73,7 +73,7 @@ LL |     if (true || let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:52:25
+  --> $DIR/disallowed-positions.rs:50:25
    |
 LL |     if true && (true || let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -82,7 +82,7 @@ LL |     if true && (true || let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:53:25
+  --> $DIR/disallowed-positions.rs:51:25
    |
 LL |     if true || (true && let 0 = 0) {}
    |                         ^^^^^^^^^
@@ -91,7 +91,7 @@ LL |     if true || (true && let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:56:12
+  --> $DIR/disallowed-positions.rs:54:12
    |
 LL |     if x = let 0 = 0 {}
    |            ^^^^^^^^^
@@ -100,7 +100,7 @@ LL |     if x = let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:59:15
+  --> $DIR/disallowed-positions.rs:57:15
    |
 LL |     if true..(let 0 = 0) {}
    |               ^^^^^^^^^
@@ -109,7 +109,7 @@ LL |     if true..(let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:61:11
+  --> $DIR/disallowed-positions.rs:59:11
    |
 LL |     if ..(let 0 = 0) {}
    |           ^^^^^^^^^
@@ -118,7 +118,7 @@ LL |     if ..(let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:63:9
+  --> $DIR/disallowed-positions.rs:61:9
    |
 LL |     if (let 0 = 0).. {}
    |         ^^^^^^^^^
@@ -127,7 +127,7 @@ LL |     if (let 0 = 0).. {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:67:8
+  --> $DIR/disallowed-positions.rs:65:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +136,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:71:8
+  --> $DIR/disallowed-positions.rs:69:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:78:8
+  --> $DIR/disallowed-positions.rs:76:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:86:8
+  --> $DIR/disallowed-positions.rs:84:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:92:19
+  --> $DIR/disallowed-positions.rs:90:19
    |
 LL |     if let true = let true = true {}
    |                   ^^^^^^^^^^^^^^^
@@ -172,7 +172,7 @@ LL |     if let true = let true = true {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:96:12
+  --> $DIR/disallowed-positions.rs:94:12
    |
 LL |     while &let 0 = 0 {}
    |            ^^^^^^^^^
@@ -181,7 +181,7 @@ LL |     while &let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:99:12
+  --> $DIR/disallowed-positions.rs:97:12
    |
 LL |     while !let 0 = 0 {}
    |            ^^^^^^^^^
@@ -190,7 +190,7 @@ LL |     while !let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:100:12
+  --> $DIR/disallowed-positions.rs:98:12
    |
 LL |     while *let 0 = 0 {}
    |            ^^^^^^^^^
@@ -199,7 +199,7 @@ LL |     while *let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:102:12
+  --> $DIR/disallowed-positions.rs:100:12
    |
 LL |     while -let 0 = 0 {}
    |            ^^^^^^^^^
@@ -208,7 +208,7 @@ LL |     while -let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:110:12
+  --> $DIR/disallowed-positions.rs:108:12
    |
 LL |     while (let 0 = 0)? {}
    |            ^^^^^^^^^
@@ -217,7 +217,7 @@ LL |     while (let 0 = 0)? {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:114:19
+  --> $DIR/disallowed-positions.rs:112:19
    |
 LL |     while true || let 0 = 0 {}
    |                   ^^^^^^^^^
@@ -226,7 +226,7 @@ LL |     while true || let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:115:20
+  --> $DIR/disallowed-positions.rs:113:20
    |
 LL |     while (true || let 0 = 0) {}
    |                    ^^^^^^^^^
@@ -235,7 +235,7 @@ LL |     while (true || let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:116:28
+  --> $DIR/disallowed-positions.rs:114:28
    |
 LL |     while true && (true || let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -244,7 +244,7 @@ LL |     while true && (true || let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:117:28
+  --> $DIR/disallowed-positions.rs:115:28
    |
 LL |     while true || (true && let 0 = 0) {}
    |                            ^^^^^^^^^
@@ -253,7 +253,7 @@ LL |     while true || (true && let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:120:15
+  --> $DIR/disallowed-positions.rs:118:15
    |
 LL |     while x = let 0 = 0 {}
    |               ^^^^^^^^^
@@ -262,7 +262,7 @@ LL |     while x = let 0 = 0 {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:123:18
+  --> $DIR/disallowed-positions.rs:121:18
    |
 LL |     while true..(let 0 = 0) {}
    |                  ^^^^^^^^^
@@ -271,7 +271,7 @@ LL |     while true..(let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:125:14
+  --> $DIR/disallowed-positions.rs:123:14
    |
 LL |     while ..(let 0 = 0) {}
    |              ^^^^^^^^^
@@ -280,7 +280,7 @@ LL |     while ..(let 0 = 0) {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:127:12
+  --> $DIR/disallowed-positions.rs:125:12
    |
 LL |     while (let 0 = 0).. {}
    |            ^^^^^^^^^
@@ -289,7 +289,7 @@ LL |     while (let 0 = 0).. {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:131:11
+  --> $DIR/disallowed-positions.rs:129:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -298,7 +298,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:135:11
+  --> $DIR/disallowed-positions.rs:133:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -307,7 +307,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:142:11
+  --> $DIR/disallowed-positions.rs:140:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -316,7 +316,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:150:11
+  --> $DIR/disallowed-positions.rs:148:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -325,7 +325,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:156:22
+  --> $DIR/disallowed-positions.rs:154:22
    |
 LL |     while let true = let true = true {}
    |                      ^^^^^^^^^^^^^^^
@@ -334,7 +334,7 @@ LL |     while let true = let true = true {}
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:170:6
+  --> $DIR/disallowed-positions.rs:168:6
    |
 LL |     &let 0 = 0;
    |      ^^^^^^^^^
@@ -343,7 +343,7 @@ LL |     &let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:172:6
+  --> $DIR/disallowed-positions.rs:170:6
    |
 LL |     !let 0 = 0;
    |      ^^^^^^^^^
@@ -352,7 +352,7 @@ LL |     !let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:173:6
+  --> $DIR/disallowed-positions.rs:171:6
    |
 LL |     *let 0 = 0;
    |      ^^^^^^^^^
@@ -361,7 +361,7 @@ LL |     *let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:175:6
+  --> $DIR/disallowed-positions.rs:173:6
    |
 LL |     -let 0 = 0;
    |      ^^^^^^^^^
@@ -370,7 +370,7 @@ LL |     -let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:183:6
+  --> $DIR/disallowed-positions.rs:181:6
    |
 LL |     (let 0 = 0)?;
    |      ^^^^^^^^^
@@ -379,7 +379,7 @@ LL |     (let 0 = 0)?;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:187:13
+  --> $DIR/disallowed-positions.rs:185:13
    |
 LL |     true || let 0 = 0;
    |             ^^^^^^^^^
@@ -388,7 +388,7 @@ LL |     true || let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:188:14
+  --> $DIR/disallowed-positions.rs:186:14
    |
 LL |     (true || let 0 = 0);
    |              ^^^^^^^^^
@@ -397,7 +397,7 @@ LL |     (true || let 0 = 0);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:189:22
+  --> $DIR/disallowed-positions.rs:187:22
    |
 LL |     true && (true || let 0 = 0);
    |                      ^^^^^^^^^
@@ -406,7 +406,7 @@ LL |     true && (true || let 0 = 0);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:192:9
+  --> $DIR/disallowed-positions.rs:190:9
    |
 LL |     x = let 0 = 0;
    |         ^^^^^^^^^
@@ -415,7 +415,7 @@ LL |     x = let 0 = 0;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:194:12
+  --> $DIR/disallowed-positions.rs:192:12
    |
 LL |     true..(let 0 = 0);
    |            ^^^^^^^^^
@@ -424,7 +424,7 @@ LL |     true..(let 0 = 0);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:195:8
+  --> $DIR/disallowed-positions.rs:193:8
    |
 LL |     ..(let 0 = 0);
    |        ^^^^^^^^^
@@ -433,7 +433,7 @@ LL |     ..(let 0 = 0);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:196:6
+  --> $DIR/disallowed-positions.rs:194:6
    |
 LL |     (let 0 = 0)..;
    |      ^^^^^^^^^
@@ -442,7 +442,7 @@ LL |     (let 0 = 0)..;
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:198:6
+  --> $DIR/disallowed-positions.rs:196:6
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -451,7 +451,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:202:6
+  --> $DIR/disallowed-positions.rs:200:6
    |
 LL |     (let true = let true = true);
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -460,7 +460,7 @@ LL |     (let true = let true = true);
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:206:6
+  --> $DIR/disallowed-positions.rs:204:6
    |
 LL |     &let 0 = 0
    |      ^^^^^^^^^
@@ -469,7 +469,7 @@ LL |     &let 0 = 0
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:217:17
+  --> $DIR/disallowed-positions.rs:215:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -478,7 +478,7 @@ LL |         true && let 1 = 1
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:221:17
+  --> $DIR/disallowed-positions.rs:219:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -487,7 +487,7 @@ LL |         true && let 1 = 1
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:225:17
+  --> $DIR/disallowed-positions.rs:223:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -496,7 +496,7 @@ LL |         true && let 1 = 1
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
 error: `let` expressions are not supported here
-  --> $DIR/disallowed-positions.rs:235:17
+  --> $DIR/disallowed-positions.rs:233:17
    |
 LL |         true && let 1 = 1
    |                 ^^^^^^^^^
@@ -504,25 +504,17 @@ LL |         true && let 1 = 1
    = note: only supported directly in conditions of `if`- and `while`-expressions
    = note: as well as when nested within `&&` and parenthesis in those conditions
 
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/disallowed-positions.rs:20:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
 warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/disallowed-positions.rs:22:12
+  --> $DIR/disallowed-positions.rs:20:12
    |
 LL | #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test.
    |            ^^^^^^^^^^
    |
+   = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:32:8
+  --> $DIR/disallowed-positions.rs:30:8
    |
 LL |     if &let 0 = 0 {}
    |        ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -534,19 +526,19 @@ LL +     if let 0 = 0 {}
    | 
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:36:8
+  --> $DIR/disallowed-positions.rs:34:8
    |
 LL |     if *let 0 = 0 {}
    |        ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:38:8
+  --> $DIR/disallowed-positions.rs:36:8
    |
 LL |     if -let 0 = 0 {}
    |        ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:46:8
+  --> $DIR/disallowed-positions.rs:44:8
    |
 LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -559,7 +551,7 @@ LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:46:19
+  --> $DIR/disallowed-positions.rs:44:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -581,7 +573,7 @@ LL |     fn from_residual(residual: R) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:56:8
+  --> $DIR/disallowed-positions.rs:54:8
    |
 LL |     if x = let 0 = 0 {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -592,7 +584,7 @@ LL |     if x == let 0 = 0 {}
    |          ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:59:8
+  --> $DIR/disallowed-positions.rs:57:8
    |
 LL |     if true..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -601,7 +593,7 @@ LL |     if true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:61:8
+  --> $DIR/disallowed-positions.rs:59:8
    |
 LL |     if ..(let 0 = 0) {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -610,7 +602,7 @@ LL |     if ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:63:8
+  --> $DIR/disallowed-positions.rs:61:8
    |
 LL |     if (let 0 = 0).. {}
    |        ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -619,7 +611,7 @@ LL |     if (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:67:12
+  --> $DIR/disallowed-positions.rs:65:12
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -630,7 +622,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:67:8
+  --> $DIR/disallowed-positions.rs:65:8
    |
 LL |     if let Range { start: _, end: _ } = true..true && false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -639,7 +631,7 @@ LL |     if let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:71:12
+  --> $DIR/disallowed-positions.rs:69:12
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -650,7 +642,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:71:8
+  --> $DIR/disallowed-positions.rs:69:8
    |
 LL |     if let Range { start: _, end: _ } = true..true || false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -659,7 +651,7 @@ LL |     if let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:78:12
+  --> $DIR/disallowed-positions.rs:76:12
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found struct `std::ops::Range`
@@ -668,16 +660,16 @@ LL |     if let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:78:41
+  --> $DIR/disallowed-positions.rs:76:41
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |                                         ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:78:41: 78:48]`
+           found closure `[closure@$DIR/disallowed-positions.rs:76:41: 76:48]`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:78:8
+  --> $DIR/disallowed-positions.rs:76:8
    |
 LL |     if let Range { start: F, end } = F..|| true {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -686,7 +678,7 @@ LL |     if let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:86:12
+  --> $DIR/disallowed-positions.rs:84:12
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -697,13 +689,13 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:86:44
+  --> $DIR/disallowed-positions.rs:84:44
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |                                            ^^^^^^^ expected `bool`, found `&&bool`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:86:8
+  --> $DIR/disallowed-positions.rs:84:8
    |
 LL |     if let Range { start: true, end } = t..&&false {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -712,7 +704,7 @@ LL |     if let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:42:20
+  --> $DIR/disallowed-positions.rs:40:20
    |
 LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
@@ -725,7 +717,7 @@ LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:96:11
+  --> $DIR/disallowed-positions.rs:94:11
    |
 LL |     while &let 0 = 0 {}
    |           ^^^^^^^^^^ expected `bool`, found `&bool`
@@ -737,19 +729,19 @@ LL +     while let 0 = 0 {}
    | 
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:100:11
+  --> $DIR/disallowed-positions.rs:98:11
    |
 LL |     while *let 0 = 0 {}
    |           ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:102:11
+  --> $DIR/disallowed-positions.rs:100:11
    |
 LL |     while -let 0 = 0 {}
    |           ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:110:11
+  --> $DIR/disallowed-positions.rs:108:11
    |
 LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -762,7 +754,7 @@ LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:110:22
+  --> $DIR/disallowed-positions.rs:108:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -784,7 +776,7 @@ LL |     fn from_residual(residual: R) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:120:11
+  --> $DIR/disallowed-positions.rs:118:11
    |
 LL |     while x = let 0 = 0 {}
    |           ^^^^^^^^^^^^^ expected `bool`, found `()`
@@ -795,7 +787,7 @@ LL |     while x == let 0 = 0 {}
    |             ~~
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:123:11
+  --> $DIR/disallowed-positions.rs:121:11
    |
 LL |     while true..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -804,7 +796,7 @@ LL |     while true..(let 0 = 0) {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:125:11
+  --> $DIR/disallowed-positions.rs:123:11
    |
 LL |     while ..(let 0 = 0) {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeTo`
@@ -813,7 +805,7 @@ LL |     while ..(let 0 = 0) {}
             found struct `RangeTo<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:127:11
+  --> $DIR/disallowed-positions.rs:125:11
    |
 LL |     while (let 0 = 0).. {}
    |           ^^^^^^^^^^^^^ expected `bool`, found struct `RangeFrom`
@@ -822,7 +814,7 @@ LL |     while (let 0 = 0).. {}
             found struct `RangeFrom<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:131:15
+  --> $DIR/disallowed-positions.rs:129:15
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -833,7 +825,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:131:11
+  --> $DIR/disallowed-positions.rs:129:11
    |
 LL |     while let Range { start: _, end: _ } = true..true && false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -842,7 +834,7 @@ LL |     while let Range { start: _, end: _ } = true..true && false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:135:15
+  --> $DIR/disallowed-positions.rs:133:15
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -853,7 +845,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:135:11
+  --> $DIR/disallowed-positions.rs:133:11
    |
 LL |     while let Range { start: _, end: _ } = true..true || false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -862,7 +854,7 @@ LL |     while let Range { start: _, end: _ } = true..true || false {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:142:15
+  --> $DIR/disallowed-positions.rs:140:15
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^ expected fn pointer, found struct `std::ops::Range`
@@ -871,16 +863,16 @@ LL |     while let Range { start: F, end } = F..|| true {}
                   found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:142:44
+  --> $DIR/disallowed-positions.rs:140:44
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |                                            ^^^^^^^ expected `bool`, found closure
    |
    = note: expected type `bool`
-           found closure `[closure@$DIR/disallowed-positions.rs:142:44: 142:51]`
+           found closure `[closure@$DIR/disallowed-positions.rs:140:44: 140:51]`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:142:11
+  --> $DIR/disallowed-positions.rs:140:11
    |
 LL |     while let Range { start: F, end } = F..|| true {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -889,7 +881,7 @@ LL |     while let Range { start: F, end } = F..|| true {}
             found struct `std::ops::Range<bool>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:150:15
+  --> $DIR/disallowed-positions.rs:148:15
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^   - this expression has type `&&bool`
@@ -900,13 +892,13 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:150:47
+  --> $DIR/disallowed-positions.rs:148:47
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |                                               ^^^^^^^ expected `bool`, found `&&bool`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:150:11
+  --> $DIR/disallowed-positions.rs:148:11
    |
 LL |     while let Range { start: true, end } = t..&&false {}
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
@@ -915,7 +907,7 @@ LL |     while let Range { start: true, end } = t..&&false {}
             found struct `std::ops::Range<bool>`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:106:23
+  --> $DIR/disallowed-positions.rs:104:23
    |
 LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
@@ -928,19 +920,19 @@ LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0614]: type `bool` cannot be dereferenced
-  --> $DIR/disallowed-positions.rs:173:5
+  --> $DIR/disallowed-positions.rs:171:5
    |
 LL |     *let 0 = 0;
    |     ^^^^^^^^^^
 
 error[E0600]: cannot apply unary operator `-` to type `bool`
-  --> $DIR/disallowed-positions.rs:175:5
+  --> $DIR/disallowed-positions.rs:173:5
    |
 LL |     -let 0 = 0;
    |     ^^^^^^^^^^ cannot apply unary operator `-`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:183:5
+  --> $DIR/disallowed-positions.rs:181:5
    |
 LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
@@ -953,7 +945,7 @@ LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
-  --> $DIR/disallowed-positions.rs:183:16
+  --> $DIR/disallowed-positions.rs:181:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
@@ -975,7 +967,7 @@ LL |     fn from_residual(residual: R) -> Self;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:198:10
+  --> $DIR/disallowed-positions.rs:196:10
    |
 LL |     (let Range { start: _, end: _ } = true..true || false);
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^   ---- this expression has type `bool`
@@ -986,7 +978,7 @@ LL |     (let Range { start: _, end: _ } = true..true || false);
             found struct `std::ops::Range<_>`
 
 error[E0308]: mismatched types
-  --> $DIR/disallowed-positions.rs:206:5
+  --> $DIR/disallowed-positions.rs:204:5
    |
 LL | fn outside_if_and_while_expr() {
    |                                - help: try adding a return type: `-> &bool`
@@ -995,7 +987,7 @@ LL |     &let 0 = 0
    |     ^^^^^^^^^^ expected `()`, found `&bool`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/disallowed-positions.rs:179:17
+  --> $DIR/disallowed-positions.rs:177:17
    |
 LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
@@ -1007,7 +999,7 @@ note: required by `branch`
 LL |     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 103 previous errors; 2 warnings emitted
+error: aborting due to 103 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0277, E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0277`.
index 1dbd000afd73ebf0debdf5058268f79e35c7d310..228b5ed71e80a833142ecd43054b0cc42fd936bb 100644 (file)
@@ -1,7 +1,5 @@
 // FIXME(fee1-dead): this should have a better error message
 #![feature(const_trait_impl)]
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
 
 struct NonConstAdd(i32);
 
@@ -14,7 +12,7 @@ fn add(self, rhs: Self) -> Self {
 }
 
 trait Foo {
-    type Bar: std::ops::Add;
+    type Bar: ~const std::ops::Add;
 }
 
 impl const Foo for NonConstAdd {
@@ -23,7 +21,7 @@ impl const Foo for NonConstAdd {
 }
 
 trait Baz {
-    type Qux: ?const std::ops::Add;
+    type Qux: std::ops::Add;
 }
 
 impl const Baz for NonConstAdd {
index ada29ba3f8b4e0a1743fd1bb6da995d14a296ed5..b894092205e433448fc0c812770e9fbace38583b 100644 (file)
@@ -1,15 +1,15 @@
 error[E0277]: cannot add `NonConstAdd` to `NonConstAdd`
-  --> $DIR/assoc-type.rs:21:5
+  --> $DIR/assoc-type.rs:19:5
    |
 LL |     type Bar = NonConstAdd;
    |     ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
    |
    = help: the trait `Add` is not implemented for `NonConstAdd`
 note: required by a bound in `Foo::Bar`
-  --> $DIR/assoc-type.rs:17:15
+  --> $DIR/assoc-type.rs:15:15
    |
-LL |     type Bar: std::ops::Add;
-   |               ^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
+LL |     type Bar: ~const std::ops::Add;
+   |               ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
 help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
    |
 LL | impl const Foo for NonConstAdd where NonConstAdd: Add {
index 536c1d737402346f87f5209e4bf0be7f11e5c01f..4b706a190e65e5985a7a3e3048ff0c1fa90e9426 100644 (file)
@@ -6,7 +6,7 @@ trait MyPartialEq {
     fn eq(&self, other: &Self) -> bool;
 }
 
-impl<T: PartialEq> const MyPartialEq for T {
+impl<T: ~const PartialEq> const MyPartialEq for T {
     fn eq(&self, other: &Self) -> bool {
         PartialEq::eq(self, other)
     }
index f3391aa63468cf91580aec8019bdd5bcb5e7a73e..adf8d4f9ea565a208c3d92cd57416df8eb54b968 100644 (file)
@@ -16,11 +16,11 @@ fn ne(&self, other: &S) -> bool {
     }
 }
 
-const fn equals_self<T: PartialEq>(t: &T) -> bool {
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
     *t == *t
 }
 
-const fn equals_self_wrapper<T: PartialEq>(t: &T) -> bool {
+const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
     equals_self(t)
 }
 
index 00a3c7f51fe90df88eeedf1b1aa9cbc2654d83db..7185376b440c8fdf10e7b029f7f94f2a4ac1acba 100644 (file)
@@ -1,9 +1,7 @@
 // check-pass
 
 #![feature(const_trait_impl)]
-#![feature(const_trait_bound_opt_out)]
 #![feature(const_fn_trait_bound)]
-#![allow(incomplete_features)]
 
 struct S;
 
@@ -16,9 +14,11 @@ fn ne(&self, other: &S) -> bool {
     }
 }
 
-// This duplicate bound should not result in ambiguities. It should be equivalent to a single const
+// This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
 // bound.
-const fn equals_self<T: PartialEq + ?const PartialEq>(t: &T) -> bool {
+// const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
+// FIXME(fee1-dead)^ why should the order matter here?
+const fn equals_self<T: ~const PartialEq + PartialEq>(t: &T) -> bool {
     *t == *t
 }
 
index dc4d5561d47459b2b44de68aa58b3a326efe22ed..e96249ff2fd5a4710f2c9b68166e438e136dc9f0 100644 (file)
@@ -1,9 +1,7 @@
 #![feature(const_fn_trait_bound)]
 #![feature(const_trait_impl)]
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
 
-pub const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
+pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
     *t == *t
     //~^ ERROR calls in constant functions are limited to constant functions
 }
index 4b2fc56aaa78a944791f288eeb42035c050ff00e..818c582869631f9bc70f22b5be7077b0d34955a7 100644 (file)
@@ -1,5 +1,5 @@
 error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/call-generic-method-fail.rs:7:5
+  --> $DIR/call-generic-method-fail.rs:5:5
    |
 LL |     *t == *t
    |     ^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-bound.rs
new file mode 100644 (file)
index 0000000..585b659
--- /dev/null
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(const_fn_trait_bound)]
+
+struct S;
+
+impl PartialEq for S {
+    fn eq(&self, _: &S) -> bool {
+        true
+    }
+}
+
+const fn equals_self<T: PartialEq>(t: &T) -> bool {
+    true
+}
+
+pub const EQ: bool = equals_self(&S);
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst-opt-out.rs
deleted file mode 100644 (file)
index 1fc2c4f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// check-pass
-
-#![feature(const_fn_trait_bound)]
-#![feature(const_trait_impl)]
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-struct S;
-
-impl PartialEq for S {
-    fn eq(&self, _: &S) -> bool {
-        true
-    }
-}
-
-const fn equals_self<T: ?const PartialEq>(t: &T) -> bool {
-    true
-}
-
-pub const EQ: bool = equals_self(&S);
-
-// Calling `equals_self` with a type that only has a non-const impl is fine, because we opted out.
-
-fn main() {}
index 8343974f8c7e756358600e41d278e2cd72249c35..6881db0aa02c3cec75158117a2e856de518efd82 100644 (file)
@@ -9,7 +9,7 @@ fn eq(&self, _: &S) -> bool {
     }
 }
 
-const fn equals_self<T: PartialEq>(t: &T) -> bool {
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
     true
 }
 
index 7cc54e0129a53e374e3db164eaa2e9fdfe5ca90d..9b9bda7c90ec7d313aab8b9096411c4c5d6acc2f 100644 (file)
@@ -8,8 +8,8 @@ LL | pub const EQ: bool = equals_self(&S);
 note: required by a bound in `equals_self`
   --> $DIR/call-generic-method-nonconst.rs:12:25
    |
-LL | const fn equals_self<T: PartialEq>(t: &T) -> bool {
-   |                         ^^^^^^^^^ required by this bound in `equals_self`
+LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+   |                         ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
 
 error: aborting due to previous error
 
index aee88d6053eee2cee24404f497867fe66abe009e..aa9bd4d824e1704aba419008433985d59c7f7727 100644 (file)
@@ -16,7 +16,7 @@ fn ne(&self, other: &S) -> bool {
     }
 }
 
-const fn equals_self<T: PartialEq>(t: &T) -> bool {
+const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
     *t == *t
 }
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr
deleted file mode 100644 (file)
index 5804145..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: fatal error triggered by #[rustc_error]
-  --> $DIR/feature-gate.rs:17:1
-   |
-LL | fn main() {}
-   | ^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs
deleted file mode 100644 (file)
index 4452ad7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// revisions: stock gated
-// gate-test-const_trait_bound_opt_out
-
-#![cfg_attr(gated, feature(const_trait_bound_opt_out))]
-#![allow(incomplete_features)]
-#![feature(rustc_attrs)]
-#![feature(const_fn_trait_bound)]
-
-trait T {
-    const CONST: i32;
-}
-
-const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
-//[stock]~^ ERROR `?const` on trait bounds is experimental
-
-#[rustc_error]
-fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr
deleted file mode 100644 (file)
index 8ae8b88..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: `?const` on trait bounds is experimental
-  --> $DIR/feature-gate.rs:13:29
-   |
-LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST }
-   |                             ^^^^^^
-   |
-   = note: see issue #67794 <https://github.com/rust-lang/rust/issues/67794> for more information
-   = help: add `#![feature(const_trait_bound_opt_out)]` 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/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs
deleted file mode 100644 (file)
index f5561a9..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![feature(const_trait_bound_opt_out)]
-#![feature(associated_type_bounds)]
-#![allow(incomplete_features)]
-
-trait T {}
-struct S;
-impl T for S {}
-
-fn rpit() -> impl ?const T { S }
-//~^ ERROR `?const` is not permitted in `impl Trait`
-
-fn apit(_: impl ?const T) {}
-//~^ ERROR `?const` is not permitted in `impl Trait`
-
-fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
-//~^ ERROR `?const` is not permitted in `impl Trait`
-
-fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
-//~^ ERROR `?const` is not permitted in `impl Trait`
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr
deleted file mode 100644 (file)
index 06cd00a..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error: `?const` is not permitted in `impl Trait`
-  --> $DIR/in-impl-trait.rs:9:19
-   |
-LL | fn rpit() -> impl ?const T { S }
-   |                   ^^^^^^^^
-
-error: `?const` is not permitted in `impl Trait`
-  --> $DIR/in-impl-trait.rs:12:17
-   |
-LL | fn apit(_: impl ?const T) {}
-   |                 ^^^^^^^^
-
-error: `?const` is not permitted in `impl Trait`
-  --> $DIR/in-impl-trait.rs:15:50
-   |
-LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) }
-   |                                                  ^^^^^^^^
-
-error: `?const` is not permitted in `impl Trait`
-  --> $DIR/in-impl-trait.rs:18:48
-   |
-LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {}
-   |                                                ^^^^^^^^
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs
deleted file mode 100644 (file)
index fc9ed5b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-trait Super {}
-trait T: ?const Super {}
-//~^ ERROR `?const` is not permitted in supertraits
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr
deleted file mode 100644 (file)
index a0d8f95..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `?const` is not permitted in supertraits
-  --> $DIR/in-trait-bounds.rs:5:10
-   |
-LL | trait T: ?const Super {}
-   |          ^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs
deleted file mode 100644 (file)
index b3d1f48..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#![feature(const_trait_bound_opt_out)]
-#![allow(bare_trait_objects)]
-#![allow(incomplete_features)]
-
-struct S;
-trait T {}
-impl T for S {}
-
-// An inherent impl for the trait object `?const T`.
-impl ?const T {}
-//~^ ERROR `?const` is not permitted in trait objects
-
-fn trait_object() -> &'static dyn ?const T { &S }
-//~^ ERROR `?const` is not permitted in trait objects
-
-fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
-//~^ ERROR `?const` is not permitted in trait objects
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr
deleted file mode 100644 (file)
index 331fe04..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error: `?const` is not permitted in trait objects
-  --> $DIR/in-trait-object.rs:10:6
-   |
-LL | impl ?const T {}
-   |      ^^^^^^^^
-
-error: `?const` is not permitted in trait objects
-  --> $DIR/in-trait-object.rs:13:35
-   |
-LL | fn trait_object() -> &'static dyn ?const T { &S }
-   |                                   ^^^^^^^^
-
-error: `?const` is not permitted in trait objects
-  --> $DIR/in-trait-object.rs:16:61
-   |
-LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
-   |                                                             ^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.rs
deleted file mode 100644 (file)
index 01e941a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// compile-flags: -Z parse-only
-
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-struct S<T: ?const ?const Tr>;
-//~^ ERROR expected identifier, found keyword `const`
-//~| ERROR expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/opt-out-twice.stderr
deleted file mode 100644 (file)
index f7924b3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: expected identifier, found keyword `const`
-  --> $DIR/opt-out-twice.rs:6:21
-   |
-LL | struct S<T: ?const ?const Tr>;
-   |                     ^^^^^ expected identifier, found keyword
-
-error: expected one of `(`, `+`, `,`, `::`, `<`, `=`, or `>`, found `Tr`
-  --> $DIR/opt-out-twice.rs:6:27
-   |
-LL | struct S<T: ?const ?const Tr>;
-   |                           ^^ expected one of 7 possible tokens
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs
deleted file mode 100644 (file)
index a0d9610..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// compile-flags: -Z parse-only
-// check-pass
-
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-struct S<
-    T: ?const ?for<'a> Tr<'a> + 'static + ?const std::ops::Add,
-    T: ?const ?for<'a: 'b> m::Trait<'a>,
->;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs
deleted file mode 100644 (file)
index c2c8689..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
-//~^ ERROR `?const` and `?` are mutually exclusive
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr
deleted file mode 100644 (file)
index e8e9d6c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `?const` and `?` are mutually exclusive
-  --> $DIR/with-maybe-sized.rs:4:13
-   |
-LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
-   |             ^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.rs
deleted file mode 100644 (file)
index b904a2e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Z parse-only
-
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
-
-struct S<T: const Tr>;
-//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/without-question-mark.stderr
deleted file mode 100644 (file)
index 0dbca95..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, lifetime, or path, found keyword `const`
-  --> $DIR/without-question-mark.rs:6:13
-   |
-LL | struct S<T: const Tr>;
-   |             ^^^^^ expected one of 9 possible tokens
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.rs
deleted file mode 100644 (file)
index 98d3a22..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(const_trait_bound_opt_out)]
-#![feature(const_trait_impl)]
-#![allow(incomplete_features)]
-
-struct S;
-trait T {}
-
-impl ?const T for S {}
-//~^ ERROR expected a trait, found type
-
-fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-opt-out-trait.stderr
deleted file mode 100644 (file)
index 8f923ef..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected a trait, found type
-  --> $DIR/impl-opt-out-trait.rs:8:6
-   |
-LL | impl ?const T for S {}
-   |      ^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.rs
new file mode 100644 (file)
index 0000000..05b2646
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+struct S;
+trait T {}
+
+impl ~const T for S {}
+//~^ ERROR expected a trait, found type
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-tilde-const-trait.stderr
new file mode 100644 (file)
index 0000000..0a91719
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected a trait, found type
+  --> $DIR/impl-tilde-const-trait.rs:6:6
+   |
+LL | impl ~const T for S {}
+   |      ^^^^^^^^
+
+error: aborting due to previous error
+
index 04123a532bd9faaf386bab563e5a96e022b1bd87..afd0d137bb4aadf8565a12443527e43e2ba5a760 100644 (file)
@@ -1,6 +1,4 @@
 #![feature(const_trait_impl)]
-#![feature(const_trait_bound_opt_out)]
-#![allow(incomplete_features)]
 #![allow(bare_trait_objects)]
 
 struct S;
index 834f6a409f5b69bcbf8c1410a51f6c365880c05f..8c55627031d1edfbaeb6636e237c39f5d5223897 100644 (file)
@@ -1,5 +1,5 @@
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:9:12
+  --> $DIR/inherent-impl.rs:7:12
    |
 LL | impl const S {}
    |      ----- ^ inherent impl for this type
@@ -9,7 +9,7 @@ LL | impl const S {}
    = note: only trait implementations may be annotated with `const`
 
 error: inherent impls cannot be `const`
-  --> $DIR/inherent-impl.rs:12:12
+  --> $DIR/inherent-impl.rs:10:12
    |
 LL | impl const T {}
    |      ----- ^ inherent impl for this type
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.rs
new file mode 100644 (file)
index 0000000..157005b
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(const_fn_trait_bound)]
+#![feature(const_trait_impl)]
+
+pub trait A {
+    fn assoc() -> bool;
+}
+
+pub const fn foo<T: A>() -> bool {
+    T::assoc()
+    //~^ ERROR calls in constant functions are limited
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-88155.stderr
new file mode 100644 (file)
index 0000000..931baac
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/issue-88155.rs:9:5
+   |
+LL |     T::assoc()
+   |     ^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
index 82a1275bffaedf89ee825a02233a49d1985306f9..7ac2458e3992850d051422629f17de153eca752f 100644 (file)
@@ -5,4 +5,4 @@
 #![feature(const_trait_impl)]
 
 // For now, this parses since an error does not occur until AST lowering.
-impl ?const T {}
+impl ~const T {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
new file mode 100644 (file)
index 0000000..b4302f3
--- /dev/null
@@ -0,0 +1,29 @@
+#![feature(const_trait_impl)]
+#![feature(associated_type_bounds)]
+
+trait T {}
+struct S;
+impl T for S {}
+
+fn rpit() -> impl ~const T { S }
+//~^ ERROR `~const` is not allowed
+
+fn apit(_: impl ~const T) {}
+//~^ ERROR `~const` is not allowed
+
+fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+//~^ ERROR `~const` is not allowed
+
+fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
+//~^ ERROR `~const` is not allowed
+
+fn generic<P: ~const T>() {}
+//~^ ERROR `~const` is not allowed
+
+fn where_clause<P>() where P: ~const T {}
+//~^ ERROR `~const` is not allowed
+
+struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+//~^ ERROR `~const` and `?` are mutually exclusive
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
new file mode 100644 (file)
index 0000000..033ec21
--- /dev/null
@@ -0,0 +1,56 @@
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:8:19
+   |
+LL | fn rpit() -> impl ~const T { S }
+   |                   ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:11:17
+   |
+LL | fn apit(_: impl ~const T) {}
+   |                 ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:14:50
+   |
+LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
+   |                                                  ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:17:48
+   |
+LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
+   |                                                ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:20:15
+   |
+LL | fn generic<P: ~const T>() {}
+   |               ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` is not allowed here
+  --> $DIR/tilde-const-invalid-places.rs:23:31
+   |
+LL | fn where_clause<P>() where P: ~const T {}
+   |                               ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error: `~const` and `?` are mutually exclusive
+  --> $DIR/tilde-const-invalid-places.rs:26:25
+   |
+LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
+   |                         ^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-syntax.rs
new file mode 100644 (file)
index 0000000..9b3c2cf
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags: -Z parse-only
+// check-pass
+
+#![feature(const_trait_impl)]
+
+struct S<
+    T: ~const ?for<'a> Tr<'a> + 'static + ~const std::ops::Add,
+    T: ~const ?for<'a: 'b> m::Trait<'a>,
+>;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.rs
new file mode 100644 (file)
index 0000000..06e4ede
--- /dev/null
@@ -0,0 +1,6 @@
+// compile-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: ~const ~const Tr>;
+//~^ ERROR expected identifier, found `~`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-twice.stderr
new file mode 100644 (file)
index 0000000..928d23e
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected identifier, found `~`
+  --> $DIR/tilde-twice.rs:5:20
+   |
+LL | struct S<T: ~const ~const Tr>;
+   |                    ^ expected identifier
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
new file mode 100644 (file)
index 0000000..0cde5b6
--- /dev/null
@@ -0,0 +1,41 @@
+// run-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+trait Bar {
+    fn bar() -> u8;
+}
+
+trait Foo {
+    #[default_method_body_is_const]
+    fn foo() -> u8 where Self: ~const Bar {
+        <Self as Bar>::bar() * 6
+    }
+}
+
+struct NonConst;
+struct Const;
+
+impl Bar for NonConst {
+    fn bar() -> u8 {
+        3
+    }
+}
+
+impl Foo for NonConst {}
+
+impl const Bar for Const {
+    fn bar() -> u8 {
+        4
+    }
+}
+
+impl const Foo for Const {}
+
+fn main() {
+    const ANS1: u8 = Const::foo();
+    let ans2 = NonConst::foo();
+
+    assert_eq!(ANS1 + ans2, 42);
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
new file mode 100644 (file)
index 0000000..ae9ab26
--- /dev/null
@@ -0,0 +1,24 @@
+// check-pass
+
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+trait Foo {
+    fn bar() where Self: ~const Foo;
+}
+
+struct S;
+
+impl Foo for S {
+    fn bar() {}
+}
+
+fn baz<T: Foo>() {
+    T::bar();
+}
+
+const fn qux<T: ~const Foo>() {
+    T::bar();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
new file mode 100644 (file)
index 0000000..d64822d
--- /dev/null
@@ -0,0 +1,40 @@
+#![feature(const_fn_trait_bound)]
+#![feature(const_trait_impl)]
+
+trait Bar {}
+
+trait Foo {
+    fn a();
+    fn b() where Self: ~const Bar;
+    fn c<T: ~const Bar>();
+}
+
+const fn test1<T: ~const Foo + Bar>() {
+    T::a();
+    T::b();
+    //~^ ERROR the trait bound
+    T::c::<T>();
+    //~^ ERROR the trait bound
+}
+
+const fn test2<T: ~const Foo + ~const Bar>() {
+    T::a();
+    T::b();
+    T::c::<T>();
+}
+
+fn test3<T: Foo>() {
+    T::a();
+    T::b();
+    //~^ ERROR the trait bound
+    T::c::<T>();
+    //~^ ERROR the trait bound
+}
+
+fn test4<T: Foo + Bar>() {
+    T::a();
+    T::b();
+    T::c::<T>();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
new file mode 100644 (file)
index 0000000..fffb91f
--- /dev/null
@@ -0,0 +1,67 @@
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:14:5
+   |
+LL |     T::b();
+   |     ^^^^ the trait `Bar` is not implemented for `T`
+   |
+note: required by `Foo::b`
+  --> $DIR/trait-where-clause.rs:8:5
+   |
+LL |     fn b() where Self: ~const Bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider further restricting this bound
+   |
+LL | const fn test1<T: ~const Foo + Bar + Bar>() {
+   |                                    +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:16:5
+   |
+LL |     T::c::<T>();
+   |     ^^^^^^^^^ the trait `Bar` is not implemented for `T`
+   |
+note: required by `Foo::c`
+  --> $DIR/trait-where-clause.rs:9:5
+   |
+LL |     fn c<T: ~const Bar>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+help: consider further restricting this bound
+   |
+LL | const fn test1<T: ~const Foo + Bar + Bar>() {
+   |                                    +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:28:5
+   |
+LL |     T::b();
+   |     ^^^^ the trait `Bar` is not implemented for `T`
+   |
+note: required by `Foo::b`
+  --> $DIR/trait-where-clause.rs:8:5
+   |
+LL |     fn b() where Self: ~const Bar;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider further restricting this bound
+   |
+LL | fn test3<T: Foo + Bar>() {
+   |                 +++++
+
+error[E0277]: the trait bound `T: Bar` is not satisfied
+  --> $DIR/trait-where-clause.rs:30:5
+   |
+LL |     T::c::<T>();
+   |     ^^^^^^^^^ the trait `Bar` is not implemented for `T`
+   |
+note: required by `Foo::c`
+  --> $DIR/trait-where-clause.rs:9:5
+   |
+LL |     fn c<T: ~const Bar>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+help: consider further restricting this bound
+   |
+LL | fn test3<T: Foo + Bar>() {
+   |                 +++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
new file mode 100644 (file)
index 0000000..96ba393
--- /dev/null
@@ -0,0 +1,6 @@
+// compiler-flags: -Z parse-only
+
+#![feature(const_trait_impl)]
+
+struct S<T: const Tr>;
+//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
new file mode 100644 (file)
index 0000000..b6b77ac
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const`
+  --> $DIR/without-tilde.rs:5:13
+   |
+LL | struct S<T: const Tr>;
+   |             ^^^^^ expected one of 10 possible tokens
+
+error: aborting due to previous error
+
index ea3ad7aed492666b10b7e68985b215089e6fb926..329fadb150fcd9586e5f39e60e5f34e881ced254 100644 (file)
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(as_array_of_cells)]
+
 use std::cell::Cell;
 
 fn main() {
@@ -8,4 +10,11 @@ fn main() {
     let slice_cell: &[Cell<i32>] = cell_slice.as_slice_of_cells();
 
     assert_eq!(slice_cell.len(), 3);
+
+    let mut array: [i32; 3] = [1, 2, 3];
+    let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array);
+    let array_cell: &[Cell<i32>; 3] = cell_array.as_array_of_cells();
+
+    array_cell[0].set(99);
+    assert_eq!(array, [99, 2, 3]);
 }
index 2cf5a073fe5c22334a30fb79d4f5b1c06f826b5f..eb4e43aaec35b4814876287c9268e0500e23c1dc 100644 (file)
@@ -8,8 +8,10 @@ LL |         x.foobar();
    |           ^^^^^^ method not found in `u32`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use crate::foo::foobar::Foobar;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use crate::foo::foobar::Foobar;
+   |
 
 error[E0599]: no method named `bar` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:28:7
diff --git a/src/test/ui/rust-2021/array-into-iter-ambiguous.fixed b/src/test/ui/rust-2021/array-into-iter-ambiguous.fixed
new file mode 100644 (file)
index 0000000..76f661b
--- /dev/null
@@ -0,0 +1,27 @@
+// See https://github.com/rust-lang/rust/issues/88475
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(array_into_iter)]
+#![allow(unused)]
+
+struct FooIter;
+
+trait MyIntoIter {
+    fn into_iter(self) -> FooIter;
+}
+
+impl<T, const N: usize> MyIntoIter for [T; N] {
+    fn into_iter(self) -> FooIter {
+        FooIter
+    }
+}
+
+struct Point;
+
+pub fn main() {
+    let points: [Point; 1] = [Point];
+    let y = MyIntoIter::into_iter(points);
+    //~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
+    //~| WARNING this changes meaning in Rust 2021
+}
diff --git a/src/test/ui/rust-2021/array-into-iter-ambiguous.rs b/src/test/ui/rust-2021/array-into-iter-ambiguous.rs
new file mode 100644 (file)
index 0000000..83fbf8f
--- /dev/null
@@ -0,0 +1,27 @@
+// See https://github.com/rust-lang/rust/issues/88475
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(array_into_iter)]
+#![allow(unused)]
+
+struct FooIter;
+
+trait MyIntoIter {
+    fn into_iter(self) -> FooIter;
+}
+
+impl<T, const N: usize> MyIntoIter for [T; N] {
+    fn into_iter(self) -> FooIter {
+        FooIter
+    }
+}
+
+struct Point;
+
+pub fn main() {
+    let points: [Point; 1] = [Point];
+    let y = points.into_iter();
+    //~^ WARNING trait method `into_iter` will become ambiguous in Rust 2021
+    //~| WARNING this changes meaning in Rust 2021
+}
diff --git a/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr b/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
new file mode 100644 (file)
index 0000000..fac8d21
--- /dev/null
@@ -0,0 +1,16 @@
+warning: trait method `into_iter` will become ambiguous in Rust 2021
+  --> $DIR/array-into-iter-ambiguous.rs:24:13
+   |
+LL |     let y = points.into_iter();
+   |             ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyIntoIter::into_iter(points)`
+   |
+note: the lint level is defined here
+  --> $DIR/array-into-iter-ambiguous.rs:5:9
+   |
+LL | #![warn(array_into_iter)]
+   |         ^^^^^^^^^^^^^^^
+   = warning: this changes meaning in Rust 2021
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.fixed
new file mode 100644 (file)
index 0000000..a1b6f5b
--- /dev/null
@@ -0,0 +1,30 @@
+// See https://github.com/rust-lang/rust/issues/88470
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+pub trait PyTryFrom<'v, T>: Sized {
+    fn try_from<V>(value: V) -> Result<&'v Self, T>;
+}
+
+pub trait PyTryInto<T>: Sized {
+    fn try_into(&self) -> Result<&T, i32>;
+}
+
+struct Foo;
+
+impl<U> PyTryInto<U> for Foo
+where
+    U: for<'v> PyTryFrom<'v, i32>,
+{
+    fn try_into(&self) -> Result<&U, i32> {
+        <U as PyTryFrom<'_, _>>::try_from(self)
+        //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+        //~| this is accepted in the current edition (Rust 2018)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.rs
new file mode 100644 (file)
index 0000000..142ba55
--- /dev/null
@@ -0,0 +1,30 @@
+// See https://github.com/rust-lang/rust/issues/88470
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
+
+pub trait PyTryFrom<'v, T>: Sized {
+    fn try_from<V>(value: V) -> Result<&'v Self, T>;
+}
+
+pub trait PyTryInto<T>: Sized {
+    fn try_into(&self) -> Result<&T, i32>;
+}
+
+struct Foo;
+
+impl<U> PyTryInto<U> for Foo
+where
+    U: for<'v> PyTryFrom<'v, i32>,
+{
+    fn try_into(&self) -> Result<&U, i32> {
+        U::try_from(self)
+        //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+        //~| this is accepted in the current edition (Rust 2018)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr
new file mode 100644 (file)
index 0000000..14ad9b0
--- /dev/null
@@ -0,0 +1,16 @@
+warning: trait-associated function `try_from` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-generic-trait.rs:24:9
+   |
+LL |         U::try_from(self)
+   |         ^^^^^^^^^^^ help: disambiguate the associated function: `<U as PyTryFrom<'_, _>>::try_from`
+   |
+note: the lint level is defined here
+  --> $DIR/future-prelude-collision-generic-trait.rs:5:9
+   |
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: 1 warning emitted
+
index f0d8cb944cf841f49f39a7929da84c78afa32005..1bb9ba3777404415cfb8bfc325815ba4fbf6a78f 100644 (file)
@@ -6,32 +6,32 @@
 #![allow(dead_code)]
 #![allow(unused_imports)]
 
-struct Generic<T, U>(T, U);
+struct Generic<'a, U>(&'a U);
 
 trait MyFromIter {
     fn from_iter(_: i32) -> Self;
 }
 
-impl MyFromIter for Generic<i32, i32> {
-    fn from_iter(x: i32) -> Self {
-        Self(x, x)
+impl MyFromIter for Generic<'static, i32> {
+    fn from_iter(_: i32) -> Self {
+        todo!()
     }
 }
 
-impl std::iter::FromIterator<i32> for Generic<i32, i32> {
+impl std::iter::FromIterator<i32> for Generic<'static, i32> {
     fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
         todo!()
     }
 }
 
 fn main() {
-    <Generic<_, _> as MyFromIter>::from_iter(1);
+    <Generic<'_, _> as MyFromIter>::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
-    <Generic::<i32, i32> as MyFromIter>::from_iter(1);
+    <Generic::<'static, i32> as MyFromIter>::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
-    <Generic::<_, _> as MyFromIter>::from_iter(1);
+    <Generic::<'_, _> as MyFromIter>::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
 }
index 1984053705984a7c82e5806ab00cba2efc77e0c5..d7f8affc61ade9e331c6a210b9cdf997dc8ec133 100644 (file)
@@ -6,19 +6,19 @@
 #![allow(dead_code)]
 #![allow(unused_imports)]
 
-struct Generic<T, U>(T, U);
+struct Generic<'a, U>(&'a U);
 
 trait MyFromIter {
     fn from_iter(_: i32) -> Self;
 }
 
-impl MyFromIter for Generic<i32, i32> {
-    fn from_iter(x: i32) -> Self {
-        Self(x, x)
+impl MyFromIter for Generic<'static, i32> {
+    fn from_iter(_: i32) -> Self {
+        todo!()
     }
 }
 
-impl std::iter::FromIterator<i32> for Generic<i32, i32> {
+impl std::iter::FromIterator<i32> for Generic<'static, i32> {
     fn from_iter<T: IntoIterator<Item = i32>>(_: T) -> Self {
         todo!()
     }
@@ -28,10 +28,10 @@ fn main() {
     Generic::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
-    Generic::<i32, i32>::from_iter(1);
+    Generic::<'static, i32>::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
-    Generic::<_, _>::from_iter(1);
+    Generic::<'_, _>::from_iter(1);
     //~^ WARNING trait-associated function `from_iter` will become ambiguous in Rust 2021
     //~| this is accepted in the current edition (Rust 2018)
 }
index 0a722baa185cd60c8722cf1a98f34ae91df603fa..e1d3f3c0a4629d972a64b025c1163b68b6e1c47d 100644 (file)
@@ -2,7 +2,7 @@ warning: trait-associated function `from_iter` will become ambiguous in Rust 202
   --> $DIR/future-prelude-collision-generic.rs:28:5
    |
 LL |     Generic::from_iter(1);
-   |     ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<_, _> as MyFromIter>::from_iter`
+   |     ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<'_, _> as MyFromIter>::from_iter`
    |
 note: the lint level is defined here
   --> $DIR/future-prelude-collision-generic.rs:5:9
@@ -15,8 +15,8 @@ LL | #![warn(rust_2021_prelude_collisions)]
 warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-generic.rs:31:5
    |
-LL |     Generic::<i32, i32>::from_iter(1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
+LL |     Generic::<'static, i32>::from_iter(1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'static, i32> as MyFromIter>::from_iter`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
@@ -24,8 +24,8 @@ LL |     Generic::<i32, i32>::from_iter(1);
 warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
   --> $DIR/future-prelude-collision-generic.rs:34:5
    |
-LL |     Generic::<_, _>::from_iter(1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
+LL |     Generic::<'_, _>::from_iter(1);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<'_, _> as MyFromIter>::from_iter`
    |
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
index c5ff0b4bcd0f8cb3bdb74fb3d3d15ca4d5316b8a..15ccff7496e096a4d2ee1d1c1f945d3bdc53313e 100644 (file)
@@ -56,4 +56,15 @@ mod c {
     }
 }
 
+mod d {
+    use super::m::*;
+
+    fn main() {
+        // See https://github.com/rust-lang/rust/issues/88471
+        let _: u32 = TryIntoU32::try_into(3u8).unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
 fn main() {}
index cd39eec47f2a4125416440a5053eee6b50d5841f..cdffcaf754541a33b99188e2ce12e6d6f24bd26e 100644 (file)
@@ -56,4 +56,15 @@ fn main() {
     }
 }
 
+mod d {
+    use super::m::*;
+
+    fn main() {
+        // See https://github.com/rust-lang/rust/issues/88471
+        let _: u32 = 3u8.try_into().unwrap();
+        //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+        //~^^ WARNING this is accepted in the current edition
+    }
+}
+
 fn main() {}
index fbda5d61f36dc070685b900b09c6e23ad381eb8a..56abb8abd4d15b9aa92d21b8a1c6b8fecc543503 100644 (file)
@@ -30,5 +30,14 @@ LL |         let _: u32 = 3u8.try_into().unwrap();
    = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
 
-warning: 3 warnings emitted
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-imported.rs:64:22
+   |
+LL |         let _: u32 = 3u8.try_into().unwrap();
+   |                      ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: 4 warnings emitted
 
diff --git a/src/test/ui/rust-2021/future-prelude-collision-macros.fixed b/src/test/ui/rust-2021/future-prelude-collision-macros.fixed
new file mode 100644 (file)
index 0000000..a97dc17
--- /dev/null
@@ -0,0 +1,45 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(unreachable_code)]
+
+macro_rules! foo {
+    () => {{
+        123;
+        S
+    }};
+}
+
+trait MyTry<T> {
+    fn try_into(self, _: u8);
+}
+
+struct S;
+
+impl MyTry<i32> for S {
+    fn try_into(self, _: u8) {}
+}
+
+trait TryFromU8: Sized {
+    fn try_from(_: u8);
+}
+
+impl TryFromU8 for u32 {
+    fn try_from(_: u8) {}
+}
+
+macro_rules! bar {
+    () => {
+        u32
+    };
+}
+
+fn main() {
+    MyTry::try_into(foo!(), todo!());
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition
+    <bar!() as TryFromU8>::try_from(0);
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-macros.rs b/src/test/ui/rust-2021/future-prelude-collision-macros.rs
new file mode 100644 (file)
index 0000000..82484b5
--- /dev/null
@@ -0,0 +1,45 @@
+// run-rustfix
+// edition:2018
+// check-pass
+#![warn(rust_2021_prelude_collisions)]
+#![allow(unreachable_code)]
+
+macro_rules! foo {
+    () => {{
+        123;
+        S
+    }};
+}
+
+trait MyTry<T> {
+    fn try_into(self, _: u8);
+}
+
+struct S;
+
+impl MyTry<i32> for S {
+    fn try_into(self, _: u8) {}
+}
+
+trait TryFromU8: Sized {
+    fn try_from(_: u8);
+}
+
+impl TryFromU8 for u32 {
+    fn try_from(_: u8) {}
+}
+
+macro_rules! bar {
+    () => {
+        u32
+    };
+}
+
+fn main() {
+    foo!().try_into(todo!());
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition
+    <bar!()>::try_from(0);
+    //~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-macros.stderr b/src/test/ui/rust-2021/future-prelude-collision-macros.stderr
new file mode 100644 (file)
index 0000000..4c3543c
--- /dev/null
@@ -0,0 +1,25 @@
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-macros.rs:39:5
+   |
+LL |     foo!().try_into(todo!());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())`
+   |
+note: the lint level is defined here
+  --> $DIR/future-prelude-collision-macros.rs:4:9
+   |
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: trait-associated function `try_from` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-macros.rs:42:5
+   |
+LL |     <bar!()>::try_from(0);
+   |     ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<bar!() as TryFromU8>::try_from`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: 2 warnings emitted
+
index e60f9c039be36cd746be8f8bff1ada996bc9bef9..e4662b430dccc7bdd9131fc4996955c95b5fde11 100644 (file)
@@ -15,9 +15,6 @@ LL |     fn try_into(self) -> Result<T, Self::Error>;
    |        the method is available for `Rc<u8>` here
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
-           candidate #1: `use crate::m::TryIntoU32;`
-           candidate #2: `use std::convert::TryInto;`
 help: consider wrapping the receiver expression with the appropriate type
    |
 LL |         let _: u32 = Box::new(3u8).try_into().unwrap();
@@ -34,6 +31,12 @@ help: consider wrapping the receiver expression with the appropriate type
    |
 LL |         let _: u32 = Rc::new(3u8).try_into().unwrap();
    |                      ++++++++   +
+help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+   |
+LL |     use crate::m::TryIntoU32;
+   |
+LL |     use std::convert::TryInto;
+   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rust-2021/future-prelude-collision-turbofish.fixed b/src/test/ui/rust-2021/future-prelude-collision-turbofish.fixed
new file mode 100644 (file)
index 0000000..3e76fce
--- /dev/null
@@ -0,0 +1,28 @@
+// See https://github.com/rust-lang/rust/issues/88442
+// run-rustfix
+// edition:2018
+// check-pass
+#![allow(unused)]
+#![warn(rust_2021_prelude_collisions)]
+
+trait AnnotatableTryInto {
+    fn try_into<T>(self) -> Result<T, Self::Error>
+    where Self: std::convert::TryInto<T> {
+        std::convert::TryInto::try_into(self)
+    }
+}
+
+impl<T> AnnotatableTryInto for T where T: From<u8> {}
+
+fn main() -> Result<(), &'static str> {
+    let x: u64 = 1;
+    AnnotatableTryInto::try_into::<usize>(x).or(Err("foo"))?.checked_sub(1);
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+
+    AnnotatableTryInto::try_into::<usize>(x).or(Err("foo"))?;
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+
+    Ok(())
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-turbofish.rs b/src/test/ui/rust-2021/future-prelude-collision-turbofish.rs
new file mode 100644 (file)
index 0000000..abb292e
--- /dev/null
@@ -0,0 +1,28 @@
+// See https://github.com/rust-lang/rust/issues/88442
+// run-rustfix
+// edition:2018
+// check-pass
+#![allow(unused)]
+#![warn(rust_2021_prelude_collisions)]
+
+trait AnnotatableTryInto {
+    fn try_into<T>(self) -> Result<T, Self::Error>
+    where Self: std::convert::TryInto<T> {
+        std::convert::TryInto::try_into(self)
+    }
+}
+
+impl<T> AnnotatableTryInto for T where T: From<u8> {}
+
+fn main() -> Result<(), &'static str> {
+    let x: u64 = 1;
+    x.try_into::<usize>().or(Err("foo"))?.checked_sub(1);
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+
+    x.try_into::<usize>().or(Err("foo"))?;
+    //~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
+    //~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+
+    Ok(())
+}
diff --git a/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr b/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr
new file mode 100644 (file)
index 0000000..2de9020
--- /dev/null
@@ -0,0 +1,25 @@
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-turbofish.rs:19:5
+   |
+LL |     x.try_into::<usize>().or(Err("foo"))?.checked_sub(1);
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::<usize>(x)`
+   |
+note: the lint level is defined here
+  --> $DIR/future-prelude-collision-turbofish.rs:6:9
+   |
+LL | #![warn(rust_2021_prelude_collisions)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: trait method `try_into` will become ambiguous in Rust 2021
+  --> $DIR/future-prelude-collision-turbofish.rs:23:5
+   |
+LL |     x.try_into::<usize>().or(Err("foo"))?;
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::<usize>(x)`
+   |
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
+
+warning: 2 warnings emitted
+
index 5882c7d83d8bebf5d54eb73f39a8e2f194863861..1994f25b6a51126961f625007bbc5cb1a5cfca65 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z unstable-options --edition 2021
+// edition:2021
 
 macro_rules! demo2 {
     ( $a:tt $b:tt ) => { println!("two tokens") };
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr
deleted file mode 100644 (file)
index 353da8f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/arbitrary-self-types-not-object-safe.rs:29:32
-   |
-LL |     fn foo(self: &Rc<Self>) -> usize;
-   |        --- method `foo`'s `self` parameter cannot be dispatched on
-...
-LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
-   |                                ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
-
-error[E0038]: the trait `Foo` cannot be made into an object
-  --> $DIR/arbitrary-self-types-not-object-safe.rs:29:13
-   |
-LL |     fn foo(self: &Rc<Self>) -> usize;
-   |        --- method `foo`'s `self` parameter cannot be dispatched on
-...
-LL |     let x = Rc::new(5usize) as Rc<dyn Foo>;
-   |             ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
-   |
-   = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
index d6ed5f61a000ef049ff838bfc138c9d2e1a935e6..45c10b378160465102f386905fbc5d5e5933f484 100644 (file)
@@ -4,7 +4,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(repr_simd, platform_intrinsics, const_generics)]
+#![feature(repr_simd, platform_intrinsics, generic_const_exprs)]
 #![allow(non_camel_case_types, incomplete_features)]
 
 pub trait Simd {
@@ -21,7 +21,7 @@ impl Simd for i32x4 {
 #[repr(simd)]
 #[derive(Copy, Clone)]
 pub struct T<S: Simd>([S::Lane; S::SIZE]);
-//~^ ERROR constant expression depends on a generic parameter
+//~^ ERROR unconstrained generic constant
 
 extern "platform-intrinsic" {
     fn simd_insert<T, E>(x: T, idx: u32, y: E) -> T;
index c100e020c5490a28882efa97cee66eb4d130edff..0e02883f67a4061f5ee45c8d09cc47af2925113f 100644 (file)
@@ -1,10 +1,10 @@
-error: constant expression depends on a generic parameter
+error: unconstrained generic constant
   --> $DIR/simd-array-trait.rs:23:23
    |
 LL | pub struct T<S: Simd>([S::Lane; S::SIZE]);
    |                       ^^^^^^^^^^^^^^^^^^
    |
-   = note: this may fail depending on what value the parameter takes
+   = help: try adding a `where` bound using this expression: `where [(); S::SIZE]:`
 
 error: aborting due to previous error
 
index 3cd0711ae42c641e9df857cf60a3c4ad3a9a6ed5..5c06254143d04a8ce52d4d4a57481083ce7033a0 100644 (file)
@@ -1,6 +1,5 @@
 #![allow(incomplete_features)]
-#![feature(const_generics)]
-#![feature(const_evaluatable_checked)]
+#![feature(generic_const_exprs)]
 #![feature(specialization)]
 
 pub trait Trait {
index 10a39a4914770d1d7890b2589adaf81cb694716f..cb46db83606b2c4a37b88d94d066facf07700f91 100644 (file)
@@ -1,5 +1,5 @@
 error: unconstrained generic constant
-  --> $DIR/issue-51892.rs:15:17
+  --> $DIR/issue-51892.rs:14:17
    |
 LL |     type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 688b6e826582610956fc49e3e50f6c56734652a2..b9714b67e58881d1e251f660d8580a9087988725 100644 (file)
@@ -10,4 +10,5 @@ fn main() {
     if Some(3) = foo {} //~ ERROR mismatched types
     //~^ ERROR destructuring assignments are unstable
     //~^^ ERROR invalid left-hand side of assignment
+    if x = 5 {}  //~ ERROR cannot find value `x` in this scope
 }
index 1e23ede7adc870716cfa1a79cab1a4440e0fdd01..7f71cb485815fc75949fd94f3b29a27d591a7b04 100644 (file)
@@ -9,6 +9,17 @@ help: you might have meant to use pattern matching
 LL |     if let Some(x) = foo {}
    |        +++
 
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/if-let-typo.rs:13:8
+   |
+LL |     if x = 5 {}
+   |        ^ not found in this scope
+   |
+help: you might have meant to use pattern matching
+   |
+LL |     if let x = 5 {}
+   |        +++
+
 error[E0658]: destructuring assignments are unstable
   --> $DIR/if-let-typo.rs:4:16
    |
@@ -79,7 +90,7 @@ error[E0308]: mismatched types
 LL |     if Some(3) = foo {}
    |        ^^^^^^^^^^^^^ expected `bool`, found `()`
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0070, E0308, E0425, E0658.
 For more information about an error, try `rustc --explain E0070`.
index 1cde42ff2cb018b4851a3905f8cfd938f071a469..bb7919ebb7996338108f03caa21f05031f67647d 100644 (file)
@@ -1,20 +1,3 @@
-error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
-  --> $DIR/impl-trait-with-missing-bounds.rs:6:13
-   |
-LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
-note: required by a bound in `qux`
-  --> $DIR/impl-trait-with-missing-bounds.rs:50:16
-   |
-LL | fn qux(_: impl std::fmt::Debug) {}
-   |                ^^^^^^^^^^^^^^^ required by this bound in `qux`
-help: introduce a type parameter with a trait bound instead of using `impl Trait`
-   |
-LL | fn foo<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug {
-   |       +++++++++++++              ~  ++++++++++++++++++++++++++++++++++
-
 error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:14:13
    |
@@ -83,6 +66,23 @@ help: introduce a type parameter with a trait bound instead of using `impl Trait
 LL | fn bak<I: Iterator + std::fmt::Debug>(constraints: I) where <I as Iterator>::Item: Debug {
    |       +++++++++++++++++++++++++++++++              ~  ++++++++++++++++++++++++++++++++++
 
+error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
+  --> $DIR/impl-trait-with-missing-bounds.rs:6:13
+   |
+LL |         qux(constraint);
+   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
+note: required by a bound in `qux`
+  --> $DIR/impl-trait-with-missing-bounds.rs:50:16
+   |
+LL | fn qux(_: impl std::fmt::Debug) {}
+   |                ^^^^^^^^^^^^^^^ required by this bound in `qux`
+help: introduce a type parameter with a trait bound instead of using `impl Trait`
+   |
+LL | fn foo<I: Iterator>(constraints: I) where <I as Iterator>::Item: Debug {
+   |       +++++++++++++              ~  ++++++++++++++++++++++++++++++++++
+
 error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:45:13
    |
index 147001f0c948b93e3d64a511174968b10cbfbdbe..1f41d2329ee9ef18780f4a6042f288072b37cabb 100644 (file)
@@ -1,11 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/suggest-ref-macro.rs:8:1
-   |
-LL | #[hello]
-   | ^^^^^^^^ expected `&mut i32`, found integer
-   |
-   = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0308]: mismatched types
   --> $DIR/suggest-ref-macro.rs:15:11
    |
@@ -29,6 +21,14 @@ LL |     bla!(456);
    |          expected `&mut i32`, found integer
    |          help: consider mutably borrowing here: `&mut 456`
 
+error[E0308]: mismatched types
+  --> $DIR/suggest-ref-macro.rs:8:1
+   |
+LL | #[hello]
+   | ^^^^^^^^ expected `&mut i32`, found integer
+   |
+   = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr
deleted file mode 100644 (file)
index 7539cba..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: symbol-name(_ZN5basic4main17hd72940ef9669d526E)
-  --> $DIR/basic.rs:3:1
-   |
-LL | #[rustc_symbol_name]
-   | ^^^^^^^^^^^^^^^^^^^^
-
-error: def-path(main)
-  --> $DIR/basic.rs:4:1
-   |
-LL | #[rustc_def_path]
-   | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
index 05c6b8352de63634f9a95f8507518befb69de33a..38b07acbdb27edfdc28b8535b46e172d1b29b550 100644 (file)
@@ -1,37 +1,37 @@
 // build-fail
-// compile-flags: -Z symbol-mangling-version=v0
+// compile-flags: -Z symbol-mangling-version=v0 --crate-name=c
 #![feature(rustc_attrs)]
 
 pub struct Unsigned<const F: u8>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
-//~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
+//~^ ERROR symbol-name(_RMCsno73SFvQKx_1cINtB0_8UnsignedKhb_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Unsigned<11u8>>)
+//~| ERROR demangling-alt(<c::Unsigned<11>>)
 impl Unsigned<11> {}
 
 pub struct Signed<const F: i16>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
-//~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
+//~^ ERROR symbol-name(_RMs_Csno73SFvQKx_1cINtB2_6SignedKsn98_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Signed<-152i16>>)
+//~| ERROR demangling-alt(<c::Signed<-152>>)
 impl Signed<-152> {}
 
 pub struct Bool<const F: bool>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
-//~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
+//~^ ERROR symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_4BoolKb1_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Bool<true>>)
+//~| ERROR demangling-alt(<c::Bool<true>>)
 impl Bool<true> {}
 
 pub struct Char<const F: char>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
-//~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
+//~^ ERROR symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_4CharKc2202_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Char<'∂'>>)
+//~| ERROR demangling-alt(<c::Char<'∂'>>)
 impl Char<'∂'> {}
 
 fn main() {}
index 05c485d001f03dab9b9b6aa18c8cd25fe72528c0..2abf293071f040bd683318ec93dedf6c4f490882 100644 (file)
@@ -1,70 +1,70 @@
-error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+error: symbol-name(_RMCsno73SFvQKx_1cINtB0_8UnsignedKhb_E)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
+error: demangling(<c[464da6a86cb672f]::Unsigned<11u8>>)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<const_generics_demangling::Unsigned<11>>)
+error: demangling-alt(<c::Unsigned<11>>)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
+error: symbol-name(_RMs_Csno73SFvQKx_1cINtB2_6SignedKsn98_E)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
+error: demangling(<c[464da6a86cb672f]::Signed<-152i16>>)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<const_generics_demangling::Signed<-152>>)
+error: demangling-alt(<c::Signed<-152>>)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
+error: symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_4BoolKb1_E)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
+error: demangling(<c[464da6a86cb672f]::Bool<true>>)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<const_generics_demangling::Bool<true>>)
+error: demangling-alt(<c::Bool<true>>)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
+error: symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_4CharKc2202_E)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
+error: demangling(<c[464da6a86cb672f]::Char<'∂'>>)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(<const_generics_demangling::Char<'∂'>>)
+error: demangling-alt(<c::Char<'∂'>>)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/const-generics-str-demangling.rs b/src/test/ui/symbol-names/const-generics-str-demangling.rs
new file mode 100644 (file)
index 0000000..f450dfe
--- /dev/null
@@ -0,0 +1,44 @@
+// build-fail
+// compile-flags: -Z symbol-mangling-version=v0 --crate-name=c
+#![feature(adt_const_params, rustc_attrs)]
+#![allow(incomplete_features)]
+
+pub struct Str<const S: &'static str>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMCsno73SFvQKx_1cINtB0_3StrKRe616263_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"abc">>)
+//~| ERROR demangling-alt(<c::Str<"abc">>)
+impl Str<"abc"> {}
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs_Csno73SFvQKx_1cINtB2_3StrKRe27_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"'">>)
+//~| ERROR demangling-alt(<c::Str<"'">>)
+impl Str<"'"> {}
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_3StrKRe090a_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"\t\n">>)
+//~| ERROR demangling-alt(<c::Str<"\t\n">>)
+impl Str<"\t\n"> {}
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_3StrKRee28882c3bc_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"∂ü">>)
+//~| ERROR demangling-alt(<c::Str<"∂ü">>)
+impl Str<"∂ü"> {}
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs2_Csno73SFvQKx_1cINtB3_3StrKRee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839be183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"საჭმელად_გემრიელი_სადილი">>)
+//~| ERROR demangling-alt(<c::Str<"საჭმელად_გემრიელი_სადილი">>)
+impl Str<"საჭმელად_გემრიელი_სადილი"> {}
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs3_Csno73SFvQKx_1cINtB3_3StrKRef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e29895f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜">>)
+//~| ERROR demangling-alt(<c::Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜">>)
+impl Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜"> {}
+
+fn main() {}
diff --git a/src/test/ui/symbol-names/const-generics-str-demangling.stderr b/src/test/ui/symbol-names/const-generics-str-demangling.stderr
new file mode 100644 (file)
index 0000000..f401997
--- /dev/null
@@ -0,0 +1,110 @@
+error: symbol-name(_RMCsno73SFvQKx_1cINtB0_3StrKRe616263_E)
+  --> $DIR/const-generics-str-demangling.rs:8:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"abc">>)
+  --> $DIR/const-generics-str-demangling.rs:8:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"abc">>)
+  --> $DIR/const-generics-str-demangling.rs:8:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs_Csno73SFvQKx_1cINtB2_3StrKRe27_E)
+  --> $DIR/const-generics-str-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"'">>)
+  --> $DIR/const-generics-str-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"'">>)
+  --> $DIR/const-generics-str-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_3StrKRe090a_E)
+  --> $DIR/const-generics-str-demangling.rs:20:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"\t\n">>)
+  --> $DIR/const-generics-str-demangling.rs:20:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"\t\n">>)
+  --> $DIR/const-generics-str-demangling.rs:20:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_3StrKRee28882c3bc_E)
+  --> $DIR/const-generics-str-demangling.rs:26:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"∂ü">>)
+  --> $DIR/const-generics-str-demangling.rs:26:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"∂ü">>)
+  --> $DIR/const-generics-str-demangling.rs:26:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs2_Csno73SFvQKx_1cINtB3_3StrKRee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839be183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_E)
+  --> $DIR/const-generics-str-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"საჭმელად_გემრიელი_სადილი">>)
+  --> $DIR/const-generics-str-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"საჭმელად_გემრიელი_სადილი">>)
+  --> $DIR/const-generics-str-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs3_Csno73SFvQKx_1cINtB3_3StrKRef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e29895f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_E)
+  --> $DIR/const-generics-str-demangling.rs:38:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜">>)
+  --> $DIR/const-generics-str-demangling.rs:38:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜">>)
+  --> $DIR/const-generics-str-demangling.rs:38:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 18 previous errors
+
diff --git a/src/test/ui/symbol-names/const-generics-structural-demangling.rs b/src/test/ui/symbol-names/const-generics-structural-demangling.rs
new file mode 100644 (file)
index 0000000..fa38848
--- /dev/null
@@ -0,0 +1,96 @@
+// build-fail
+// compile-flags: -Z symbol-mangling-version=v0 --crate-name=c
+
+// NOTE(eddyb) we need `core` for `core::option::Option`, normalize away its
+// disambiguator hash, which can/should change (including between stage{1,2}).
+// normalize-stderr-test: "Cs[0-9a-zA-Z]+_4core" -> "Cs$$HASH_4core"
+// normalize-stderr-test: "core\[[0-9a-f]+\]" -> "core[$$HASH_HEX]"
+
+#![feature(adt_const_params, decl_macro, rustc_attrs)]
+#![allow(incomplete_features)]
+
+pub struct RefByte<const RB: &'static u8>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMCsno73SFvQKx_1cINtB0_7RefByteKRh7b_E)
+//~| ERROR demangling(<c[464da6a86cb672f]::RefByte<{&123u8}>>)
+//~| ERROR demangling-alt(<c::RefByte<{&123}>>)
+impl RefByte<{&123}> {}
+
+// FIXME(eddyb) this was supposed to be `RefMutZst` with `&mut []`,
+// but that is currently not allowed in const generics.
+pub struct RefZst<const RMZ: &'static [u8; 0]>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs_Csno73SFvQKx_1cINtB2_6RefZstKRAEE)
+//~| ERROR demangling(<c[464da6a86cb672f]::RefZst<{&[]}>>)
+//~| ERROR demangling-alt(<c::RefZst<{&[]}>>)
+impl RefZst<{&[]}> {}
+
+pub struct Array3Bytes<const A3B: [u8; 3]>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_11Array3BytesKAh1_h2_h3_EE)
+//~| ERROR demangling(<c[464da6a86cb672f]::Array3Bytes<{[1u8, 2u8, 3u8]}>>)
+//~| ERROR demangling-alt(<c::Array3Bytes<{[1, 2, 3]}>>)
+impl Array3Bytes<{[1, 2, 3]}> {}
+
+pub struct TupleByteBool<const TBB: (u8, bool)>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_13TupleByteBoolKTh1_b0_EE)
+//~| ERROR demangling(<c[464da6a86cb672f]::TupleByteBool<{(1u8, false)}>>)
+//~| ERROR demangling-alt(<c::TupleByteBool<{(1, false)}>>)
+impl TupleByteBool<{(1, false)}> {}
+
+pub struct OptionUsize<const OU: Option<usize>>;
+
+// HACK(eddyb) the full mangling is only in `.stderr` because we can normalize
+// the `core` disambiguator hash away there, but not here.
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs2_Csno73SFvQKx_1cINtB3_11OptionUsizeKVNtINtNtCs
+//~| ERROR demangling(<c[464da6a86cb672f]::OptionUsize<{core[
+//~| ERROR demangling-alt(<c::OptionUsize<{core::option::Option::<usize>::None}>>)
+impl OptionUsize<{None}> {}
+
+// HACK(eddyb) the full mangling is only in `.stderr` because we can normalize
+// the `core` disambiguator hash away there, but not here.
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs3_Csno73SFvQKx_1cINtB3_11OptionUsizeKVNtINtNtCs
+//~| ERROR demangling(<c[464da6a86cb672f]::OptionUsize<{core[
+//~| ERROR demangling-alt(<c::OptionUsize<{core::option::Option::<usize>::Some(0)}>>)
+impl OptionUsize<{Some(0)}> {}
+
+#[derive(PartialEq, Eq)]
+pub struct Foo {
+    s: &'static str,
+    ch: char,
+    slice: &'static [u8],
+}
+pub struct Foo_<const F: Foo>;
+
+#[rustc_symbol_name]
+//~^ ERROR symbol-name(_RMs4_Csno73SFvQKx_1cINtB3_4Foo_KVNtB3_3FooS1sRe616263_2chc78_5sliceRAh1_h2_h3_EEE)
+//~| ERROR demangling(<c[464da6a86cb672f]::Foo_<{c[464da6a86cb672f]::Foo { s: "abc", ch: 'x', slice: &[1u8, 2u8, 3u8] }}>>)
+//~| ERROR demangling-alt(<c::Foo_<{c::Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}>>)
+impl Foo_<{Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}> {}
+
+// NOTE(eddyb) this tests specifically the use of disambiguators in field names,
+// using macros 2.0 hygiene to create a `struct` with conflicting field names.
+macro duplicate_field_name_test($x:ident) {
+    #[derive(PartialEq, Eq)]
+    pub struct Bar {
+        $x: u8,
+        x: u16,
+    }
+    pub struct Bar_<const B: Bar>;
+
+    #[rustc_symbol_name]
+    //~^ ERROR symbol-name(_RMs9_Csno73SFvQKx_1cINtB3_4Bar_KVNtB3_3BarS1xh7b_s_1xt1000_EE)
+    //~| ERROR demangling(<c[464da6a86cb672f]::Bar_<{c[464da6a86cb672f]::Bar { x: 123u8, x: 4096u16 }}>>)
+    //~| ERROR demangling-alt(<c::Bar_<{c::Bar { x: 123, x: 4096 }}>>)
+    impl Bar_<{Bar { $x: 123, x: 4096 }}> {}
+}
+duplicate_field_name_test!(x);
+
+fn main() {}
diff --git a/src/test/ui/symbol-names/const-generics-structural-demangling.stderr b/src/test/ui/symbol-names/const-generics-structural-demangling.stderr
new file mode 100644 (file)
index 0000000..b3c5bd2
--- /dev/null
@@ -0,0 +1,161 @@
+error: symbol-name(_RMCsno73SFvQKx_1cINtB0_7RefByteKRh7b_E)
+  --> $DIR/const-generics-structural-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::RefByte<{&123u8}>>)
+  --> $DIR/const-generics-structural-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::RefByte<{&123}>>)
+  --> $DIR/const-generics-structural-demangling.rs:14:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs_Csno73SFvQKx_1cINtB2_6RefZstKRAEE)
+  --> $DIR/const-generics-structural-demangling.rs:24:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::RefZst<{&[]}>>)
+  --> $DIR/const-generics-structural-demangling.rs:24:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::RefZst<{&[]}>>)
+  --> $DIR/const-generics-structural-demangling.rs:24:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs0_Csno73SFvQKx_1cINtB3_11Array3BytesKAh1_h2_h3_EE)
+  --> $DIR/const-generics-structural-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Array3Bytes<{[1u8, 2u8, 3u8]}>>)
+  --> $DIR/const-generics-structural-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Array3Bytes<{[1, 2, 3]}>>)
+  --> $DIR/const-generics-structural-demangling.rs:32:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs1_Csno73SFvQKx_1cINtB3_13TupleByteBoolKTh1_b0_EE)
+  --> $DIR/const-generics-structural-demangling.rs:40:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::TupleByteBool<{(1u8, false)}>>)
+  --> $DIR/const-generics-structural-demangling.rs:40:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::TupleByteBool<{(1, false)}>>)
+  --> $DIR/const-generics-structural-demangling.rs:40:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs2_Csno73SFvQKx_1cINtB3_11OptionUsizeKVNtINtNtCs$HASH_4core6option6OptionjE4NoneUE)
+  --> $DIR/const-generics-structural-demangling.rs:50:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::OptionUsize<{core[$HASH_HEX]::option::Option::<usize>::None}>>)
+  --> $DIR/const-generics-structural-demangling.rs:50:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::OptionUsize<{core::option::Option::<usize>::None}>>)
+  --> $DIR/const-generics-structural-demangling.rs:50:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs3_Csno73SFvQKx_1cINtB3_11OptionUsizeKVNtINtNtCs$HASH_4core6option6OptionjE4SomeTj0_EE)
+  --> $DIR/const-generics-structural-demangling.rs:58:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::OptionUsize<{core[$HASH_HEX]::option::Option::<usize>::Some(0usize)}>>)
+  --> $DIR/const-generics-structural-demangling.rs:58:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::OptionUsize<{core::option::Option::<usize>::Some(0)}>>)
+  --> $DIR/const-generics-structural-demangling.rs:58:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs4_Csno73SFvQKx_1cINtB3_4Foo_KVNtB3_3FooS1sRe616263_2chc78_5sliceRAh1_h2_h3_EEE)
+  --> $DIR/const-generics-structural-demangling.rs:72:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<c[464da6a86cb672f]::Foo_<{c[464da6a86cb672f]::Foo { s: "abc", ch: 'x', slice: &[1u8, 2u8, 3u8] }}>>)
+  --> $DIR/const-generics-structural-demangling.rs:72:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<c::Foo_<{c::Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] }}>>)
+  --> $DIR/const-generics-structural-demangling.rs:72:1
+   |
+LL | #[rustc_symbol_name]
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RMs9_Csno73SFvQKx_1cINtB3_4Bar_KVNtB3_3BarS1xh7b_s_1xt1000_EE)
+  --> $DIR/const-generics-structural-demangling.rs:88:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+...
+LL | duplicate_field_name_test!(x);
+   | ------------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: demangling(<c[464da6a86cb672f]::Bar_<{c[464da6a86cb672f]::Bar { x: 123u8, x: 4096u16 }}>>)
+  --> $DIR/const-generics-structural-demangling.rs:88:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+...
+LL | duplicate_field_name_test!(x);
+   | ------------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: demangling-alt(<c::Bar_<{c::Bar { x: 123, x: 4096 }}>>)
+  --> $DIR/const-generics-structural-demangling.rs:88:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+...
+LL | duplicate_field_name_test!(x);
+   | ------------------------------ in this macro invocation
+   |
+   = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 24 previous errors
+
index 960049be7936f032248a61d60a608564ec3f08c7..60f19266ba9fc7a146fe615e1a31c73ec9924e34 100644 (file)
@@ -64,7 +64,7 @@ fn method(&self) {}
             //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
             //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
              //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-                //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+                //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
                 //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
             //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
index a7c3a389909a4f75eb72f329f21258c07b64eb3a..926e750e3cda711bf384cf20ad5f011e2f75298a 100644 (file)
@@ -52,7 +52,7 @@ error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KC
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
index 98bfcb8d67b516eafb8948ee05d6a0c8a48f32bb..94e718317e7c8c79c79ad2df655d3b9f3c4c475f 100644 (file)
@@ -25,6 +25,7 @@ struct Runtime<DB: Database> {
 }
 struct SalsaStorage {
     _parse: <ParseQuery as Query<RootDatabase>>::Data,
+    //~^ ERROR overflow
 }
 
 impl Database for RootDatabase {
@@ -67,7 +68,6 @@ pub(crate) fn goto_implementation(db: &RootDatabase) -> u32 {
     // we used to fail to report an error here because we got the
     // caching wrong.
     SourceDatabase::parse(db);
-    //~^ ERROR overflow
     22
 }
 
index 565899677bf1a74d55e7d39acf7d304edfcf2150..9452e11e302e318eca4fc884087be42ec4837f0d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
-  --> $DIR/cycle-cache-err-60010.rs:69:5
+  --> $DIR/cycle-cache-err-60010.rs:27:13
    |
-LL |     SourceDatabase::parse(db);
-   |     ^^^^^^^^^^^^^^^^^^^^^
+LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: required because it appears within the type `*const SalsaStorage`
    = note: required because it appears within the type `Unique<SalsaStorage>`
@@ -18,15 +18,15 @@ note: required because it appears within the type `RootDatabase`
 LL | struct RootDatabase {
    |        ^^^^^^^^^^^^
 note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
-  --> $DIR/cycle-cache-err-60010.rs:43:9
+  --> $DIR/cycle-cache-err-60010.rs:44:9
    |
 LL | impl<T> SourceDatabase for T
    |         ^^^^^^^^^^^^^^     ^
-note: required by `SourceDatabase::parse`
-  --> $DIR/cycle-cache-err-60010.rs:14:5
+note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
+  --> $DIR/cycle-cache-err-60010.rs:37:10
    |
-LL |     fn parse(&self) {
-   |     ^^^^^^^^^^^^^^^
+LL | impl<DB> Query<DB> for ParseQuery
+   |          ^^^^^^^^^     ^^^^^^^^^^
 
 error: aborting due to previous error
 
index 072c46bc21e9a36ea0f8db890d1a36594ee9ff87..8be42fc4ad07fb277537d32476d40bf29618789e 100644 (file)
@@ -15,8 +15,8 @@ impl<'a> Y for C<'a> {
 struct C<'a>(&'a ());
 struct X<T: Y>(T::P);
 
-impl<T: NotAuto> NotAuto for Box<T> {}
-impl<T: Y> NotAuto for X<T> where T::P: NotAuto {} //~ NOTE: required
+impl<T: NotAuto> NotAuto for Box<T> {} //~ NOTE: required
+impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
 impl<'a> NotAuto for C<'a> {}
 
 fn is_send<S: NotAuto>() {}
@@ -26,6 +26,6 @@ fn main() {
     // Should only be a few notes.
     is_send::<X<C<'static>>>();
     //~^ ERROR overflow evaluating
-    //~| 2 redundant requirements hidden
+    //~| 3 redundant requirements hidden
     //~| required because of
 }
index 2905deb940f3a504d191c21e2cc9fab48c07ce19..2ffcdb0e1c6dec5826e5313a229b2f3f8daabb69 100644 (file)
@@ -1,15 +1,15 @@
-error[E0275]: overflow evaluating the requirement `Box<X<C<'_>>>: NotAuto`
+error[E0275]: overflow evaluating the requirement `X<C<'_>>: NotAuto`
   --> $DIR/lifetime.rs:27:5
    |
 LL |     is_send::<X<C<'static>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required because of the requirements on the impl of `NotAuto` for `X<C<'_>>`
-  --> $DIR/lifetime.rs:19:12
+note: required because of the requirements on the impl of `NotAuto` for `Box<X<C<'_>>>`
+  --> $DIR/lifetime.rs:18:18
    |
-LL | impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
-   |            ^^^^^^^     ^^^^
-   = note: 2 redundant requirements hidden
+LL | impl<T: NotAuto> NotAuto for Box<T> {}
+   |                  ^^^^^^^     ^^^^^^
+   = note: 3 redundant requirements hidden
    = note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
 note: required by a bound in `is_send`
   --> $DIR/lifetime.rs:22:15
index 7eb1c9ffb3b49d2cf3b97884215971f1c4edf85e..230c2638c50037458910032827ef8fbf18b64971 100644 (file)
@@ -1,4 +1,4 @@
-error[E0275]: overflow evaluating the requirement `{integer}: Tweedledee`
+error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
   --> $DIR/simultaneous.rs:18:5
    |
 LL |     is_ee(4);
index 7d7f6ea30ae317de20a342300e4bfefe54fafe59..1f81fa72547df3e32df878ca6aa03c6be8ce2791 100644 (file)
@@ -8,8 +8,12 @@ LL |     T: FnMut(&'a ()),
 note: required by a bound in `FnMut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
-LL | pub trait FnMut<Args>: FnOnce<Args> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FnMut`
+LL | / pub trait FnMut<Args>: FnOnce<Args> {
+LL | |     /// Performs the call operation.
+LL | |     #[unstable(feature = "fn_traits", issue = "29625")]
+LL | |     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+LL | | }
+   | |_^ required by this bound in `FnMut`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.rs b/src/test/ui/traits/vtable/vtable-non-object-safe.rs
new file mode 100644 (file)
index 0000000..45b6a8a
--- /dev/null
@@ -0,0 +1,18 @@
+// build-fail
+#![feature(rustc_attrs)]
+
+// Ensure that non-object-safe methods in Iterator does not generate
+// vtable entries.
+
+#[rustc_dump_vtable]
+trait A: Iterator {}
+//~^ error Vtable
+
+impl<T> A for T where T: Iterator {}
+
+fn foo(_a: &mut dyn A<Item=u8>) {
+}
+
+fn main() {
+    foo(&mut vec![0, 1, 2, 3].into_iter());
+}
diff --git a/src/test/ui/traits/vtable/vtable-non-object-safe.stderr b/src/test/ui/traits/vtable/vtable-non-object-safe.stderr
new file mode 100644 (file)
index 0000000..f3175b8
--- /dev/null
@@ -0,0 +1,16 @@
+error: Vtable entries for `<std::vec::IntoIter<u8> as A>`: [
+    MetadataDropInPlace,
+    MetadataSize,
+    MetadataAlign,
+    Method(<std::vec::IntoIter<u8> as Iterator>::next),
+    Method(<std::vec::IntoIter<u8> as Iterator>::size_hint),
+    Method(<std::vec::IntoIter<u8> as Iterator>::advance_by),
+    Method(<std::vec::IntoIter<u8> as Iterator>::nth),
+]
+  --> $DIR/vtable-non-object-safe.rs:8:1
+   |
+LL | trait A: Iterator {}
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index ebea94171f2ab698ac32f42f79921b945f9182e3..429ce523799f3e0faa4bd1d93ac4956884ab2132 100644 (file)
@@ -1,22 +1,25 @@
 // build-fail
 #![feature(rustc_attrs)]
+#![feature(negative_impls)]
+#![allow(where_clauses_object_safety)]
 
 // B --> A
 
 #[rustc_dump_vtable]
 trait A {
     fn foo_a1(&self) {}
-    fn foo_a2(&self) where Self: Sized {}
+    fn foo_a2(&self) where Self: Send {}
 }
 
 #[rustc_dump_vtable]
 trait B: A {
     //~^ error Vtable
     fn foo_b1(&self) {}
-    fn foo_b2() where Self: Sized {}
+    fn foo_b2(&self) where Self: Send {}
 }
 
 struct S;
+impl !Send for S {}
 
 impl A for S {}
 impl B for S {}
index 768cca526894ac81ecd6f1ade8e0140fc4234b89..f5cd36264fcff94e5a17668c667412e3c23dc376 100644 (file)
@@ -7,12 +7,12 @@ error: Vtable entries for `<S as B>`: [
     Method(<S as B>::foo_b1),
     Vacant,
 ]
-  --> $DIR/vtable-vacant.rs:13:1
+  --> $DIR/vtable-vacant.rs:15:1
    |
 LL | / trait B: A {
 LL | |
 LL | |     fn foo_b1(&self) {}
-LL | |     fn foo_b2() where Self: Sized {}
+LL | |     fn foo_b2(&self) where Self: Send {}
 LL | | }
    | |_^
 
index 1d520613a288f29d52a490e1335a51e9787f3486..37543c137f66f861d4dbf23e8d50afa15c09b35a 100644 (file)
@@ -5,6 +5,12 @@ LL |     <E>::V();
    |     ^^^^^^-- supplied 0 arguments
    |     |
    |     expected 1 argument
+   |
+note: tuple variant defined here
+  --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:5:5
+   |
+LL |     V(u8)
+   |     ^
 
 error[E0308]: mismatched types
   --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.rs b/src/test/ui/type-alias-impl-trait/argument-types.rs
new file mode 100644 (file)
index 0000000..8427b5b
--- /dev/null
@@ -0,0 +1,28 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+
+// FIXME: This should compile, but it currently doesn't
+fn foo1(mut x: Foo) {
+    x = 22_u32;
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn foo2(mut x: Foo) {
+    // no constraint on x
+}
+
+fn foo3(x: Foo) {
+    println!("{:?}", x);
+}
+
+fn foo_value() -> Foo {
+    11_u32
+}
+
+fn main() {
+    foo3(foo_value());
+}
diff --git a/src/test/ui/type-alias-impl-trait/argument-types.stderr b/src/test/ui/type-alias-impl-trait/argument-types.stderr
new file mode 100644 (file)
index 0000000..1cbf9c9
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/argument-types.rs:10:9
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     x = 22_u32;
+   |         ^^^^^^ expected opaque type, found `u32`
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index d53f562e99f4bf8ee866c554f5b0a1bb7cdcde09..0ade36dafa4f335f1d1e7eb87c52df6efdacf882 100644 (file)
@@ -3,8 +3,6 @@
 // check-pass
 
 #![feature(type_alias_impl_trait)]
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
 
 trait UnwrapItemsExt<'a, const C: usize> {
     type Iter;
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr
deleted file mode 100644 (file)
index e0c1b02..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/assoc-type-const.rs:6:12
-   |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage.rs
new file mode 100644 (file)
index 0000000..a158458
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+mod m {
+    type Foo = impl std::fmt::Debug;
+
+    pub fn foo() -> Foo {
+        22_u32
+    }
+}
+
+fn is_send<T: Send>(_: T) {}
+
+fn main() {
+    is_send(m::foo());
+}
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs
new file mode 100644 (file)
index 0000000..745379e
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+mod m {
+    use std::rc::Rc;
+
+    type Foo = impl std::fmt::Debug;
+
+    pub fn foo() -> Foo {
+        Rc::new(22_u32)
+    }
+}
+
+fn is_send<T: Send>(_: T) {}
+
+fn main() {
+    is_send(m::foo());
+    //~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277]
+}
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
new file mode 100644 (file)
index 0000000..d60be4b
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0277]: `Rc<u32>` cannot be sent between threads safely
+  --> $DIR/auto-trait-leakage2.rs:17:5
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                -------------------- within this `impl Debug`
+...
+LL |     is_send(m::foo());
+   |     ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+   |
+   = help: within `impl Debug`, the trait `Send` is not implemented for `Rc<u32>`
+   = note: required because it appears within the type `impl Debug`
+note: required by a bound in `is_send`
+  --> $DIR/auto-trait-leakage2.rs:14:15
+   |
+LL | fn is_send<T: Send>(_: T) {}
+   |               ^^^^ required by this bound in `is_send`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.rs
new file mode 100644 (file)
index 0000000..5fb7a94
--- /dev/null
@@ -0,0 +1,21 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME This should compile, but it currently doesn't
+
+mod m {
+    type Foo = impl std::fmt::Debug;
+    //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+
+    pub fn foo() -> Foo {
+        22_u32
+    }
+
+    pub fn bar() {
+        is_send(foo());
+    }
+
+    fn is_send<T: Send>(_: T) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
new file mode 100644 (file)
index 0000000..86b3f87
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/auto-trait-leakage3.rs:7:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/auto-trait-leakage3.rs:15:9
+   |
+LL |         is_send(foo());
+   |         ^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/auto-trait-leakage3.rs:6:1
+   |
+LL | mod m {
+   | ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr b/src/test/ui/type-alias-impl-trait/bounds-are-checked-2.full_tait.stderr
deleted file mode 100644 (file)
index 3ba04af..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/bounds-are-checked-2.rs:6:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/bounds-are-checked-2.rs:9:13
-   |
-LL | type X<T> = impl Clone;
-   |             ^^^^^^^^^^ the trait `Clone` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | type X<T: std::clone::Clone> = impl Clone;
-   |         +++++++++++++++++++
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/field-types.rs b/src/test/ui/type-alias-impl-trait/field-types.rs
new file mode 100644 (file)
index 0000000..91494a8
--- /dev/null
@@ -0,0 +1,20 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME This should compile, but it currently doesn't
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+//~^ ERROR: could not find defining uses
+
+struct Bar {
+    foo: Foo,
+}
+
+fn bar() -> Bar {
+    Bar { foo: "foo" }
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/field-types.stderr b/src/test/ui/type-alias-impl-trait/field-types.stderr
new file mode 100644 (file)
index 0000000..18c2abb
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/field-types.rs:16:16
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     Bar { foo: "foo" }
+   |                ^^^^^ expected opaque type, found `&str`
+   |
+   = note: expected opaque type `impl Debug`
+                found reference `&'static str`
+
+error: could not find defining uses
+  --> $DIR/field-types.rs:8:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index e45950c4926b13fd11e1337f781fed428b084eab..a4e40f516dcefd7bd9769f58d4cf479afc883a5f 100644 (file)
@@ -1,6 +1,4 @@
-#![feature(const_generics)]
 #![feature(type_alias_impl_trait)]
-#![allow(incomplete_features)]
 
 use std::fmt::Debug;
 
index 7ea5efd4e6b02841a2e85882aa42eb1986ea93b8..641cce26d99446027b948a3fb02c4f15f641ac8d 100644 (file)
@@ -1,35 +1,35 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:14:30
+  --> $DIR/generic_duplicate_param_use.rs:12:30
    |
 LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
    |                              ^^^^^^^^^^^^
    |
 note: type used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:10:13
+  --> $DIR/generic_duplicate_param_use.rs:8:13
    |
 LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:19:36
+  --> $DIR/generic_duplicate_param_use.rs:17:36
    |
 LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
    |                                    ^^^^^^^^^^^^^^^^^^^^
    |
 note: lifetime used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:11:19
+  --> $DIR/generic_duplicate_param_use.rs:9:19
    |
 LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                   ^^  ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:24:50
+  --> $DIR/generic_duplicate_param_use.rs:22:50
    |
 LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
    |                                                  ^^^^^^^^^^^^^^^
    |
 note: constant used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:12:22
+  --> $DIR/generic_duplicate_param_use.rs:10:22
    |
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                      ^               ^
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.full_tait.stderr
deleted file mode 100644 (file)
index 918121c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_duplicate_param_use5.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use5.rs:19:1
-   |
-LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, U)`, got `(U, T)`
-   |
-note: previous use here
-  --> $DIR/generic_duplicate_param_use5.rs:15:1
-   |
-LL | fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use5.rs:11:18
-   |
-LL | type Two<T, U> = impl Debug;
-   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use5.rs:11:18
-   |
-LL | type Two<T, U> = impl Debug;
-   |                  ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
-help: consider restricting type parameter `U`
-   |
-LL | type Two<T, U: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.full_tait.stderr
deleted file mode 100644 (file)
index 394b428..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_duplicate_param_use6.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use6.rs:18:1
-   |
-LL | fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, T)`, got `(U, T)`
-   |
-note: previous use here
-  --> $DIR/generic_duplicate_param_use6.rs:14:1
-   |
-LL | fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use6.rs:11:18
-   |
-LL | type Two<T, U> = impl Debug;
-   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required because of the requirements on the impl of `Debug` for `(T, T)`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.full_tait.stderr
deleted file mode 100644 (file)
index 8c6ea3b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_duplicate_param_use8.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use8.rs:17:1
-   |
-LL | fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
-   |
-note: previous use here
-  --> $DIR/generic_duplicate_param_use8.rs:13:1
-   |
-LL | fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use8.rs:10:18
-   |
-LL | type Two<T, U> = impl Debug;
-   |                  ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-   = note: required because of the requirements on the impl of `Debug` for `(T, u32)`
-help: consider restricting type parameter `T`
-   |
-LL | type Two<T: std::fmt::Debug, U> = impl Debug;
-   |           +++++++++++++++++
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.full_tait.stderr
deleted file mode 100644 (file)
index d0176b1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_duplicate_param_use9.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use9.rs:24:1
-   |
-LL | fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
-   |
-note: previous use here
-  --> $DIR/generic_duplicate_param_use9.rs:20:1
-   |
-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)`
-  --> $DIR/generic_duplicate_param_use9.rs:10:18
-   |
-LL | type Two<A, B> = impl Debug;
-   |                  ^^^^^^^^^^ within `(A, B, <A as Foo>::Bar)`, 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;
-   |           +++++
-
-error[E0277]: `A` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use9.rs:10:18
-   |
-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)`
-help: consider restricting type parameter `A`
-   |
-LL | type Two<A: std::fmt::Debug, B> = impl Debug;
-   |           +++++++++++++++++
-
-error[E0277]: `B` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use9.rs:10:18
-   |
-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)`
-help: consider restricting type parameter `B`
-   |
-LL | type Two<A, B: std::fmt::Debug> = impl Debug;
-   |              +++++++++++++++++
-
-error: aborting due to 4 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
index 9f1bffff77c97fd34b47dd3c2a7268376f63ba49..7ee5f7b068f451c4ad64786a5d81bda7c57f5342 100644 (file)
@@ -1,6 +1,4 @@
-#![feature(const_generics)]
 #![feature(type_alias_impl_trait)]
-#![allow(incomplete_features)]
 
 use std::fmt::Debug;
 
index eb0c296bb626a565b53d1ebf0c908cdc002c0a0f..5b42f10a6ee34a19ab01ddc65a2d27876212e2ff 100644 (file)
@@ -1,17 +1,17 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:15:21
+  --> $DIR/generic_nondefining_use.rs:13:21
    |
 LL | fn concrete_ty() -> OneTy<u32> {
    |                     ^^^^^^^^^^
    |
 note: used non-generic type `u32` for generic parameter
-  --> $DIR/generic_nondefining_use.rs:9:12
+  --> $DIR/generic_nondefining_use.rs:7:12
    |
 LL | type OneTy<T> = impl Debug;
    |            ^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:20:27
+  --> $DIR/generic_nondefining_use.rs:18:27
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -20,13 +20,13 @@ LL | fn concrete_lifetime() -> OneLifetime<'static> {
    |                           ^^^^^^^^^^^^^^^^^^^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:25:24
+  --> $DIR/generic_nondefining_use.rs:23:24
    |
 LL | fn concrete_const() -> OneConst<{ 123 }> {
    |                        ^^^^^^^^^^^^^^^^^
    |
-note: used non-generic constant `{ 123 }` for generic parameter
-  --> $DIR/generic_nondefining_use.rs:11:21
+note: used non-generic constant `123_usize` for generic parameter
+  --> $DIR/generic_nondefining_use.rs:9:21
    |
 LL | type OneConst<const X: usize> = impl Debug;
    |                     ^
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.full_tait.stderr
deleted file mode 100644 (file)
index 74d5c0c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-error: at least one trait must be specified
-  --> $DIR/generic_underconstrained.rs:9:35
-   |
-LL | type Underconstrained<T: Trait> = impl 'static;
-   |                                   ^^^^^^^^^^^^
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_underconstrained.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/generic_underconstrained.rs:13:31
-   |
-LL | type Underconstrained<T: Trait> = impl 'static;
-   |                          ----- required by this bound in `Underconstrained`
-...
-LL | fn underconstrain<T>(_: T) -> Underconstrained<T> {
-   |                               ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> {
-   |                    +++++++
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.full_tait.stderr
deleted file mode 100644 (file)
index 348563b..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-error: at least one trait must be specified
-  --> $DIR/generic_underconstrained2.rs:8:45
-   |
-LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
-   |                                             ^^^^^^^^^^^^
-
-error: at least one trait must be specified
-  --> $DIR/generic_underconstrained2.rs:17:46
-   |
-LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
-   |                                              ^^^^^^^^^^^^
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/generic_underconstrained2.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:12:33
-   |
-LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
-   |                          --------------- required by this bound in `Underconstrained`
-...
-LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
-   |                                 ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-help: consider restricting type parameter `U`
-   |
-LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
-   |                      +++++++++++++++++
-
-error[E0277]: `V` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:21:43
-   |
-LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
-   |                           --------------- required by this bound in `Underconstrained2`
-...
-LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
-   |                                           ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug`
-   |
-help: consider restricting type parameter `V`
-   |
-LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained2<V> {
-   |                          +++++++++++++++++
-
-error: aborting due to 4 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.rs b/src/test/ui/type-alias-impl-trait/inference-cycle.rs
new file mode 100644 (file)
index 0000000..c781e20
--- /dev/null
@@ -0,0 +1,26 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+mod m {
+    type Foo = impl std::fmt::Debug;
+    //~^ ERROR: cycle detected when computing type of `m::Foo::{opaque#0}` [E0391]
+
+    // Cycle: error today, but it'd be nice if it eventually worked
+
+    pub fn foo() -> Foo {
+        is_send(bar())
+    }
+
+    pub fn bar() {
+        is_send(foo()); // Today: error
+    }
+
+    fn baz() {
+        let f: Foo = 22_u32;
+        //~^ ERROR: mismatched types [E0308]
+    }
+
+    fn is_send<T: Send>(_: T) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/inference-cycle.stderr b/src/test/ui/type-alias-impl-trait/inference-cycle.stderr
new file mode 100644 (file)
index 0000000..4c5921c
--- /dev/null
@@ -0,0 +1,37 @@
+error[E0391]: cycle detected when computing type of `m::Foo::{opaque#0}`
+  --> $DIR/inference-cycle.rs:5:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires type-checking `m::bar`...
+  --> $DIR/inference-cycle.rs:15:9
+   |
+LL |         is_send(foo()); // Today: error
+   |         ^^^^^^^
+   = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+   = note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
+note: cycle used when checking item types in module `m`
+  --> $DIR/inference-cycle.rs:4:1
+   |
+LL | mod m {
+   | ^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/inference-cycle.rs:19:22
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                -------------------- the expected opaque type
+...
+LL |         let f: Foo = 22_u32;
+   |                ---   ^^^^^^ expected opaque type, found `u32`
+   |                |
+   |                expected due to this
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0308, E0391.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr b/src/test/ui/type-alias-impl-trait/issue-52843.full_tait.stderr
deleted file mode 100644 (file)
index 16b1830..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-52843.rs:3:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0277]: the trait bound `T: Default` is not satisfied
-  --> $DIR/issue-52843.rs:6:15
-   |
-LL | type Foo<T> = impl Default;
-   |               ^^^^^^^^^^^^ the trait `Default` is not implemented for `T`
-   |
-help: consider restricting type parameter `T`
-   |
-LL | type Foo<T: std::default::Default> = impl Default;
-   |           +++++++++++++++++++++++
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference.rs
new file mode 100644 (file)
index 0000000..efb88da
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+type FooX = impl Debug;
+
+trait Foo<A> { }
+
+impl Foo<()> for () { }
+
+fn foo() -> impl Foo<FooX> {
+    ()
+}
+
+fn main() { }
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.rs
new file mode 100644 (file)
index 0000000..9b26a65
--- /dev/null
@@ -0,0 +1,19 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::fmt::Debug;
+
+type FooX = impl Debug;
+//~^ ERROR: could not find defining uses
+
+trait Foo<A> {}
+
+impl Foo<()> for () {}
+impl Foo<u32> for () {}
+
+fn foo() -> impl Foo<FooX> {
+    //~^ ERROR: the trait bound `(): Foo<impl Debug>` is not satisfied [E0277]
+    ()
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr
new file mode 100644 (file)
index 0000000..7e24ee6
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `(): Foo<impl Debug>` is not satisfied
+  --> $DIR/nested-tait-inference2.rs:14:13
+   |
+LL | fn foo() -> impl Foo<FooX> {
+   |             ^^^^^^^^^^^^^^ the trait `Foo<impl Debug>` is not implemented for `()`
+   |
+   = help: the following implementations were found:
+             <() as Foo<()>>
+             <() as Foo<u32>>
+
+error: could not find defining uses
+  --> $DIR/nested-tait-inference2.rs:6:13
+   |
+LL | type FooX = impl Debug;
+   |             ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs
new file mode 100644 (file)
index 0000000..f630d27
--- /dev/null
@@ -0,0 +1,16 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME: This should compile, but it currently doesn't
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+//~^ ERROR: could not find defining uses
+
+static FOO1: Foo = 22_u32;
+//~^ ERROR: mismatched types [E0308]
+const FOO2: Foo = 22_u32;
+//~^ ERROR: mismatched types [E0308]
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr
new file mode 100644 (file)
index 0000000..72083d0
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+  --> $DIR/static-const-types.rs:11:20
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL | static FOO1: Foo = 22_u32;
+   |                    ^^^^^^ expected opaque type, found `u32`
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/static-const-types.rs:13:19
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL | const FOO2: Foo = 22_u32;
+   |                   ^^^^^^ expected opaque type, found `u32`
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error: could not find defining uses
+  --> $DIR/static-const-types.rs:8:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.rs b/src/test/ui/type-alias-impl-trait/type_of_a_let.rs
new file mode 100644 (file)
index 0000000..7f8e612
--- /dev/null
@@ -0,0 +1,29 @@
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// FIXME This should compile, but it currently doesn't
+
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+//~^ ERROR: could not find defining uses
+
+fn foo1() -> u32 {
+    let x: Foo = 22_u32;
+    //~^ ERROR: mismatched types [E0308]
+    x
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn foo2() -> u32 {
+    let x: Foo = 22_u32;
+    //~^ ERROR: mismatched types [E0308]
+    let y: Foo = x;
+    same_type((x, y));
+    y
+    //~^ ERROR: mismatched types [E0308]
+}
+
+fn same_type<T>(x: (T, T)) {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr b/src/test/ui/type-alias-impl-trait/type_of_a_let.stderr
new file mode 100644 (file)
index 0000000..cac8d68
--- /dev/null
@@ -0,0 +1,67 @@
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:12:18
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     let x: Foo = 22_u32;
+   |            ---   ^^^^^^ expected opaque type, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:14:5
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the found opaque type
+...
+LL | fn foo1() -> u32 {
+   |              --- expected `u32` because of return type
+...
+LL |     x
+   |     ^ expected `u32`, found opaque type
+   |
+   = note:     expected type `u32`
+           found opaque type `impl Debug`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:19:18
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the expected opaque type
+...
+LL |     let x: Foo = 22_u32;
+   |            ---   ^^^^^^ expected opaque type, found `u32`
+   |            |
+   |            expected due to this
+   |
+   = note: expected opaque type `impl Debug`
+                     found type `u32`
+
+error[E0308]: mismatched types
+  --> $DIR/type_of_a_let.rs:23:5
+   |
+LL | type Foo = impl Debug;
+   |            ---------- the found opaque type
+...
+LL | fn foo2() -> u32 {
+   |              --- expected `u32` because of return type
+...
+LL |     y
+   |     ^ expected `u32`, found opaque type
+   |
+   = note:     expected type `u32`
+           found opaque type `impl Debug`
+
+error: could not find defining uses
+  --> $DIR/type_of_a_let.rs:8:12
+   |
+LL | type Foo = impl Debug;
+   |            ^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/weird-return-types.rs b/src/test/ui/type-alias-impl-trait/weird-return-types.rs
new file mode 100644 (file)
index 0000000..faad5ee
--- /dev/null
@@ -0,0 +1,16 @@
+// edition:2018
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+use std::future::Future;
+use std::fmt::Debug;
+
+type Foo = impl Debug;
+
+fn f() -> impl Future<Output = Foo> {
+    async move { 22_u32 }
+}
+
+fn main() {}
index 96ee422b7b9dd570a2b0cfed5727bd663b97b403..43f0fbbc4e387d266d8bddbc87fe7a6138de3c95 100644 (file)
@@ -3,6 +3,16 @@ error[E0425]: cannot find value `input_cells` in this scope
    |
 LL |         input_cells: Vec::new()
    |         ^^^^^^^^^^^ a field by this name exists in `Self`
+   |
+help: you might have meant to write a `struct` literal
+   |
+LL ~     pub fn new() -> Self { SomeStruct {
+LL |         input_cells: Vec::new()
+LL |
+LL |
+LL |
+LL ~     }}
+   |
 
 error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
   --> $DIR/issue-34255-1.rs:7:27
index d77ef73028b0cd7ff06db0edf08506a8f4aff136..6e99feed33f9c9d99c43ceeb17961e0c319aee5d 100644 (file)
@@ -29,6 +29,12 @@ LL |     let _ = Wrapper();
    |             ^^^^^^^-- supplied 0 arguments
    |             |
    |             expected 1 argument
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:2:8
+   |
+LL | struct Wrapper(i32);
+   |        ^^^^^^^
 
 error[E0061]: this struct takes 1 argument but 2 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:10:13
@@ -37,6 +43,12 @@ LL |     let _ = Wrapper(5, 2);
    |             ^^^^^^^ -  - supplied 2 arguments
    |             |
    |             expected 1 argument
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:2:8
+   |
+LL | struct Wrapper(i32);
+   |        ^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 0 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:11:13
@@ -45,6 +57,12 @@ LL |     let _ = DoubleWrapper();
    |             ^^^^^^^^^^^^^-- supplied 0 arguments
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 1 argument was supplied
   --> $DIR/struct-enum-wrong-args.rs:12:13
@@ -53,6 +71,12 @@ LL |     let _ = DoubleWrapper(5);
    |             ^^^^^^^^^^^^^ - supplied 1 argument
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error[E0061]: this struct takes 2 arguments but 3 arguments were supplied
   --> $DIR/struct-enum-wrong-args.rs:13:13
@@ -61,6 +85,12 @@ LL |     let _ = DoubleWrapper(5, 2, 7);
    |             ^^^^^^^^^^^^^ -  -  - supplied 3 arguments
    |             |
    |             expected 2 arguments
+   |
+note: tuple struct defined here
+  --> $DIR/struct-enum-wrong-args.rs:3:8
+   |
+LL | struct DoubleWrapper(i32, i32);
+   |        ^^^^^^^^^^^^^
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
deleted file mode 100644 (file)
index 6ba28c3..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:157:18
-   |
-LL | struct BadStruct<_>(_);
-   |                  ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:160:16
-   |
-LL | trait BadTrait<_> {}
-   |                ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:170:19
-   |
-LL | struct BadStruct1<_, _>(_);
-   |                   ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:170:22
-   |
-LL | struct BadStruct1<_, _>(_);
-   |                      ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/typeck_type_placeholder_item.rs:175:19
-   |
-LL | struct BadStruct2<_, T>(_, T);
-   |                   ^ expected identifier, found reserved identifier
-
-error: associated constant in `impl` without body
-  --> $DIR/typeck_type_placeholder_item.rs:208:5
-   |
-LL |     const C: _;
-   |     ^^^^^^^^^^-
-   |               |
-   |               help: provide a definition for the constant: `= <expr>;`
-
-error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters
-  --> $DIR/typeck_type_placeholder_item.rs:170:22
-   |
-LL | struct BadStruct1<_, _>(_);
-   |                   -  ^ already used
-   |                   |
-   |                   first use of `_`
-
-warning: the feature `type_alias_impl_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/typeck_type_placeholder_item.rs:5:32
-   |
-LL | #![cfg_attr(full_tait, feature(type_alias_impl_trait))]
-   |                                ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:10:14
-   |
-LL | fn test() -> _ { 5 }
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct return type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:13:16
-   |
-LL | fn test2() -> (_, _) { (5, 5) }
-   |               -^--^-
-   |               ||  |
-   |               ||  not allowed in type signatures
-   |               |not allowed in type signatures
-   |               help: replace with the correct return type: `(i32, i32)`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:16:15
-   |
-LL | static TEST3: _ = "test";
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `&str`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:19:15
-   |
-LL | static TEST4: _ = 145;
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:22:15
-   |
-LL | static TEST5: (_, _) = (1, 2);
-   |               ^^^^^^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:25:13
-   |
-LL | fn test6(_: _) { }
-   |             ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | fn test6<T>(_: T) { }
-   |         +++    ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:28:18
-   |
-LL | fn test6_b<T>(_: _, _: T) { }
-   |                  ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | fn test6_b<T, U>(_: U, _: T) { }
-   |             +++     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:31:30
-   |
-LL | fn test6_c<T, K, L, A, B>(_: _, _: (T, K, L, A, B)) { }
-   |                              ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | fn test6_c<T, K, L, A, B, U>(_: U, _: (T, K, L, A, B)) { }
-   |                         +++     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:34:13
-   |
-LL | fn test7(x: _) { let _x: usize = x; }
-   |             ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | fn test7<T>(x: T) { let _x: usize = x; }
-   |         +++    ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:37:22
-   |
-LL | fn test8(_f: fn() -> _) { }
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: use type parameters instead: `T`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:37:22
-   |
-LL | fn test8(_f: fn() -> _) { }
-   |                      ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | fn test8<T>(_f: fn() -> T) { }
-   |         +++             ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:51:26
-   |
-LL | fn test11(x: &usize) -> &_ {
-   |                         -^
-   |                         ||
-   |                         |not allowed in type signatures
-   |                         help: replace with the correct return type: `&'static &'static usize`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:56:52
-   |
-LL | unsafe fn test12(x: *const usize) -> *const *const _ {
-   |                                      --------------^
-   |                                      |             |
-   |                                      |             not allowed in type signatures
-   |                                      help: replace with the correct return type: `*const *const usize`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:70:8
-   |
-LL |     a: _,
-   |        ^ not allowed in type signatures
-LL |
-LL |     b: (_, _),
-   |         ^  ^ not allowed in type signatures
-   |         |
-   |         not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL ~ struct Test10<T> {
-LL ~     a: T,
-LL |
-LL ~     b: (T, T),
-   |
-
-error: missing type for `static` item
-  --> $DIR/typeck_type_placeholder_item.rs:76:12
-   |
-LL |     static A = 42;
-   |            ^ help: provide a type for the static variable: `A: i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:78:15
-   |
-LL |     static B: _ = 42;
-   |               ^
-   |               |
-   |               not allowed in type signatures
-   |               help: replace with the correct type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:80:15
-   |
-LL |     static C: Option<_> = Some(42);
-   |               ^^^^^^^^^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:82:21
-   |
-LL |     fn fn_test() -> _ { 5 }
-   |                     ^
-   |                     |
-   |                     not allowed in type signatures
-   |                     help: replace with the correct return type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:85:23
-   |
-LL |     fn fn_test2() -> (_, _) { (5, 5) }
-   |                      -^--^-
-   |                      ||  |
-   |                      ||  not allowed in type signatures
-   |                      |not allowed in type signatures
-   |                      help: replace with the correct return type: `(i32, i32)`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:88:22
-   |
-LL |     static FN_TEST3: _ = "test";
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: replace with the correct type: `&str`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:91:22
-   |
-LL |     static FN_TEST4: _ = 145;
-   |                      ^
-   |                      |
-   |                      not allowed in type signatures
-   |                      help: replace with the correct type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for static variables
-  --> $DIR/typeck_type_placeholder_item.rs:94:22
-   |
-LL |     static FN_TEST5: (_, _) = (1, 2);
-   |                      ^^^^^^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:97:20
-   |
-LL |     fn fn_test6(_: _) { }
-   |                    ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn fn_test6<T>(_: T) { }
-   |                +++    ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:100:20
-   |
-LL |     fn fn_test7(x: _) { let _x: usize = x; }
-   |                    ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn fn_test7<T>(x: T) { let _x: usize = x; }
-   |                +++    ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:103:29
-   |
-LL |     fn fn_test8(_f: fn() -> _) { }
-   |                             ^
-   |                             |
-   |                             not allowed in type signatures
-   |                             help: use type parameters instead: `T`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:103:29
-   |
-LL |     fn fn_test8(_f: fn() -> _) { }
-   |                             ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn fn_test8<T>(_f: fn() -> T) { }
-   |                +++             ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:126:12
-   |
-LL |         a: _,
-   |            ^ not allowed in type signatures
-LL |
-LL |         b: (_, _),
-   |             ^  ^ not allowed in type signatures
-   |             |
-   |             not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL ~     struct FnTest10<T> {
-LL ~         a: T,
-LL |
-LL ~         b: (T, T),
-   |
-
-error[E0282]: type annotations needed
-  --> $DIR/typeck_type_placeholder_item.rs:131:18
-   |
-LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
-   |                  ^ cannot infer type
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:131:28
-   |
-LL |     fn fn_test11(_: _) -> (_, _) { panic!() }
-   |                            ^  ^ not allowed in type signatures
-   |                            |
-   |                            not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:135:30
-   |
-LL |     fn fn_test12(x: i32) -> (_, _) { (x, x) }
-   |                             -^--^-
-   |                             ||  |
-   |                             ||  not allowed in type signatures
-   |                             |not allowed in type signatures
-   |                             help: replace with the correct return type: `(i32, i32)`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:138:33
-   |
-LL |     fn fn_test13(x: _) -> (i32, _) { (x, x) }
-   |                           ------^-
-   |                           |     |
-   |                           |     not allowed in type signatures
-   |                           help: replace with the correct return type: `(i32, i32)`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:157:21
-   |
-LL | struct BadStruct<_>(_);
-   |                     ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct<T>(T);
-   |                  ~  ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for implementations
-  --> $DIR/typeck_type_placeholder_item.rs:162:15
-   |
-LL | impl BadTrait<_> for BadStruct<_> {}
-   |               ^                ^ not allowed in type signatures
-   |               |
-   |               not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | impl<T> BadTrait<T> for BadStruct<T> {}
-   |     +++          ~                ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
-  --> $DIR/typeck_type_placeholder_item.rs:165:34
-   |
-LL | fn impl_trait() -> impl BadTrait<_> {
-   |                                  ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:170:25
-   |
-LL | struct BadStruct1<_, _>(_);
-   |                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct1<T, _>(T);
-   |                   ~     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for structs
-  --> $DIR/typeck_type_placeholder_item.rs:175:25
-   |
-LL | struct BadStruct2<_, T>(_, T);
-   |                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL | struct BadStruct2<U, T>(U, T);
-   |                   ~     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for type aliases
-  --> $DIR/typeck_type_placeholder_item.rs:179:14
-   |
-LL | type X = Box<_>;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for opaque types
-  --> $DIR/typeck_type_placeholder_item.rs:185:21
-   |
-LL | type Y = impl Trait<_>;
-   |                     ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:219:31
-   |
-LL | fn value() -> Option<&'static _> {
-   |               ----------------^-
-   |               |               |
-   |               |               not allowed in type signatures
-   |               help: replace with the correct return type: `Option<&'static u8>`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:224:10
-   |
-LL | const _: Option<_> = map(value);
-   |          ^^^^^^^^^
-   |          |
-   |          not allowed in type signatures
-   |          help: replace with the correct type: `Option<u8>`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:143:31
-   |
-LL |     fn method_test1(&self, x: _);
-   |                               ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn method_test1<T>(&self, x: T);
-   |                    +++           ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:145:31
-   |
-LL |     fn method_test2(&self, x: _) -> _;
-   |                               ^     ^ not allowed in type signatures
-   |                               |
-   |                               not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn method_test2<T>(&self, x: T) -> T;
-   |                    +++           ~     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:147:31
-   |
-LL |     fn method_test3(&self) -> _;
-   |                               ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn method_test3<T>(&self) -> T;
-   |                    +++           ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:149:26
-   |
-LL |     fn assoc_fn_test1(x: _);
-   |                          ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn assoc_fn_test1<T>(x: T);
-   |                      +++    ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:151:26
-   |
-LL |     fn assoc_fn_test2(x: _) -> _;
-   |                          ^     ^ not allowed in type signatures
-   |                          |
-   |                          not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn assoc_fn_test2<T>(x: T) -> T;
-   |                      +++    ~     ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:153:28
-   |
-LL |     fn assoc_fn_test3() -> _;
-   |                            ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn assoc_fn_test3<T>() -> T;
-   |                      +++      ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:193:14
-   |
-LL |     type B = _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:195:14
-   |
-LL |     const C: _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:197:14
-   |
-LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:200:26
-   |
-LL |     type F: std::ops::Fn(_);
-   |                          ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:44:24
-   |
-LL |     fn test9(&self) -> _ { () }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:47:27
-   |
-LL |     fn test10(&self, _x : _) { }
-   |                           ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn test10<T>(&self, _x : T) { }
-   |              +++             ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:62:24
-   |
-LL |     fn clone(&self) -> _ { Test9 }
-   |                        ^
-   |                        |
-   |                        not allowed in type signatures
-   |                        help: replace with the correct return type: `Test9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:65:37
-   |
-LL |     fn clone_from(&mut self, other: _) { *self = Test9; }
-   |                                     ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |     fn clone_from<T>(&mut self, other: T) { *self = Test9; }
-   |                  +++                   ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:110:31
-   |
-LL |         fn fn_test9(&self) -> _ { () }
-   |                               ^
-   |                               |
-   |                               not allowed in type signatures
-   |                               help: replace with the correct return type: `()`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:113:34
-   |
-LL |         fn fn_test10(&self, _x : _) { }
-   |                                  ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |         fn fn_test10<T>(&self, _x : T) { }
-   |                     +++             ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:118:28
-   |
-LL |         fn clone(&self) -> _ { FnTest9 }
-   |                            ^
-   |                            |
-   |                            not allowed in type signatures
-   |                            help: replace with the correct return type: `FnTest9`
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/typeck_type_placeholder_item.rs:121:41
-   |
-LL |         fn clone_from(&mut self, other: _) { *self = FnTest9; }
-   |                                         ^ not allowed in type signatures
-   |
-help: use type parameters instead
-   |
-LL |         fn clone_from<T>(&mut self, other: T) { *self = FnTest9; }
-   |                      +++                   ~
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:204:14
-   |
-LL |     type A = _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:206:14
-   |
-LL |     type B = _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:208:14
-   |
-LL |     const C: _;
-   |              ^ not allowed in type signatures
-
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:211:14
-   |
-LL |     const D: _ = 42;
-   |              ^
-   |              |
-   |              not allowed in type signatures
-   |              help: replace with the correct type: `i32`
-
-error: aborting due to 69 previous errors; 1 warning emitted
-
-Some errors have detailed explanations: E0121, E0282, E0403.
-For more information about an error, try `rustc --explain E0121`.
index eb16fa9d5660b49fa5c90344a539ef42afa061e2..7faede4e6d0a9ac40af902e954e3191861237f2b 100644 (file)
@@ -5,8 +5,10 @@ LL |         x.deref();
    |           ^^^^^ method not found in `&()`
    |
    = help: items from traits can only be used if the trait is in scope
-   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
-           `use std::ops::Deref;`
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+   |
+LL |     use std::ops::Deref;
+   |
 
 error: aborting due to previous error
 
index 414d2759a47982bc68cfd9d6da163256895fb4fb..b52117cd19cca32b262e4228f63bd1f42c56dfa1 100644 (file)
@@ -1,16 +1,3 @@
-error[E0277]: the trait bound `U1: Copy` is not satisfied
-  --> $DIR/union-derive-clone.rs:6:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^ the trait `Copy` is not implemented for `U1`
-   |
-note: required by a bound in `AssertParamIsCopy`
-  --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
   --> $DIR/union-derive-clone.rs:38:15
    |
@@ -30,6 +17,19 @@ LL |     let w = u.clone();
            `CloneNoCopy: Copy`
            which is required by `U5<CloneNoCopy>: Clone`
 
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   |
+note: required by a bound in `AssertParamIsCopy`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0599.
index 414d2759a47982bc68cfd9d6da163256895fb4fb..b52117cd19cca32b262e4228f63bd1f42c56dfa1 100644 (file)
@@ -1,16 +1,3 @@
-error[E0277]: the trait bound `U1: Copy` is not satisfied
-  --> $DIR/union-derive-clone.rs:6:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^ the trait `Copy` is not implemented for `U1`
-   |
-note: required by a bound in `AssertParamIsCopy`
-  --> $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
-   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
 error[E0599]: the method `clone` exists for union `U5<CloneNoCopy>`, but its trait bounds were not satisfied
   --> $DIR/union-derive-clone.rs:38:15
    |
@@ -30,6 +17,19 @@ LL |     let w = u.clone();
            `CloneNoCopy: Copy`
            which is required by `U5<CloneNoCopy>: Clone`
 
+error[E0277]: the trait bound `U1: Copy` is not satisfied
+  --> $DIR/union-derive-clone.rs:6:10
+   |
+LL | #[derive(Clone)]
+   |          ^^^^^ the trait `Copy` is not implemented for `U1`
+   |
+note: required by a bound in `AssertParamIsCopy`
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
+   |
+LL | pub struct AssertParamIsCopy<T: Copy + ?Sized> {
+   |                                 ^^^^ required by this bound in `AssertParamIsCopy`
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0599.
index 84a7eb2ef2e72c5aa8aa6fbe0e5e936da5e22ea2..318b00ddea94e703636a8f370d913bd025880b8c 100644 (file)
@@ -55,10 +55,10 @@ LL |     let U1 { a } = u1;
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
 error[E0133]: access to union field is unsafe and requires unsafe function or block
-  --> $DIR/union-unsafe.rs:65:20
+  --> $DIR/union-unsafe.rs:65:12
    |
 LL |     if let U1 { a: 12 } = u1 {}
-   |                    ^^ access to union field
+   |            ^^^^^^^^^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
 
diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.rs b/src/test/ui/unsized/param-mentioned-by-different-field.rs
new file mode 100644 (file)
index 0000000..cda94b3
--- /dev/null
@@ -0,0 +1,10 @@
+// We must not allow this with our current setup as `T`
+// is mentioned both in the tail of `Foo` and by another
+// field.
+struct Foo<T: ?Sized>(Box<T>, T);
+
+fn main() {
+    let x: Foo<[u8; 1]> = Foo(Box::new([2]), [3]);
+    let y: &Foo<[u8]> = &x; //~ ERROR mismatched types
+    assert_eq!(y.0.len(), 1);
+}
diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.stderr b/src/test/ui/unsized/param-mentioned-by-different-field.stderr
new file mode 100644 (file)
index 0000000..d18fa64
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/param-mentioned-by-different-field.rs:8:25
+   |
+LL |     let y: &Foo<[u8]> = &x;
+   |            ----------   ^^ expected slice `[u8]`, found array `[u8; 1]`
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&Foo<[u8]>`
+              found reference `&Foo<[u8; 1]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index e96bdb0c3d0a418e7fcd7fbd69be08abf830b4bc..18751dd3f238d94d384a7fe967abfac06cbfe0b9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e96bdb0c3d0a418e7fcd7fbd69be08abf830b4bc
+Subproject commit 18751dd3f238d94d384a7fe967abfac06cbfe0b9
index 62a119d662bb251f1cb3a0af16dff3b8817bc41a..5dcf1824ef0b7e3d387d0507f8f987a0ccf011df 100644 (file)
@@ -3,9 +3,9 @@
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind, GenericArg};
 use rustc_lint::LateContext;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
-use rustc_target::abi::LayoutOf;
 
 use super::CAST_PTR_ALIGNMENT;
 
index 8b0e9e6bc9b9344548a88096bf63a8a744e41a22..1ba241d37761675150a31b80e2e30cc4dc76023e 100644 (file)
@@ -5,11 +5,11 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::FakeReadCause;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, TraitRef, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::kw;
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
 use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
@@ -53,7 +53,7 @@ fn is_non_trait_box(ty: Ty<'_>) -> bool {
 struct EscapeDelegate<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
     set: HirIdSet,
-    trait_self_ty: Option<Ty<'a>>,
+    trait_self_ty: Option<Ty<'tcx>>,
     too_large_for_stack: u64,
 }
 
@@ -171,7 +171,8 @@ fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
                 // skip if there is a `self` parameter binding to a type
                 // that contains `Self` (i.e.: `self: Box<Self>`), see #4804
                 if let Some(trait_self_ty) = self.trait_self_ty {
-                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(cmt.place.ty(), trait_self_ty) {
+                    if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty)
+                    {
                         return;
                     }
                 }
index 3b28b1212048a1b20de55a1e613858fb236c76cd..b1f70b30c12cf1c1605b09ac48cf9fc9891fad3e 100644 (file)
@@ -2,10 +2,10 @@
 
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, IntTy, UintTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
-use rustc_target::abi::LayoutOf;
 
 use clippy_utils::comparisons::Rel;
 use clippy_utils::consts::{constant, Constant};
index 5d4e06c2af08247cfab92f51b4274eba66210b38..10281496c11cbb4e65887c6ea5e17447d17a2ab3 100644 (file)
@@ -1,10 +1,10 @@
-use crate::rustc_target::abi::LayoutOf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{BytePos, Pos, Span};
index cde2336b690fd04753a06b56f8298b0e998b4bea..e4b8e7546283b460f6f40da388ae8b3c51453d3c 100644 (file)
@@ -6,8 +6,8 @@
 use rustc_hir::{Item, ItemKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_target::abi::LayoutOf;
 
 declare_clippy_lint! {
     /// ### What it does
index 7088630bfdbb45f56c27a73aedfc043127f84894..bbb6c1f902ce077e7fcfc6f168021f71fb356cde 100644 (file)
@@ -4,11 +4,10 @@
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 
-use crate::rustc_target::abi::LayoutOf;
-
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for local arrays that may be too large.
index 8992d25932cad00981a950a4c18b223dbc6b9afa..89146b4dd2c9bd5f58b61a89a2cab4b61f7b6d76 100644 (file)
@@ -119,7 +119,7 @@ fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
             if let Some(init) = local.init;
             then {
                 let init_ty = cx.typeck_results().expr_ty(init);
-                let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
+                let contains_sync_guard = init_ty.walk(cx.tcx).any(|inner| match inner.unpack() {
                     GenericArgKind::Type(inner_ty) => {
                         SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
                     },
index 0f6cd5de761f9d394402900b5079fa9ea8ee6ff6..545498a10478db9c623f979edee7a70bf3f54d37 100644 (file)
@@ -49,7 +49,7 @@ fn emit_lint(cx: &LateContext<'_>, vec: &Expr<'_>, pushed_item: &Expr<'_>) {
         if same_item_push_visitor.should_lint();
         if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push;
         let vec_ty = cx.typeck_results().expr_ty(vec);
-        let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
+        let ty = vec_ty.walk(cx.tcx).nth(1).unwrap().expect_ty();
         if cx
             .tcx
             .lang_items()
index a371f8bbd3cb43100959c54d924dc8105fd2291c..39f7ade3f81f6cbbf8c824e9c58f9820b1d40d64 100644 (file)
@@ -47,11 +47,8 @@ pub struct MacroRefData {
 
 impl MacroRefData {
     pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self {
-        let mut path = cx
-            .sess()
-            .source_map()
-            .span_to_filename(callee)
-            .prefer_local()
+        let sm = cx.sess().source_map();
+        let mut path = sm.filename_for_diagnostics(&sm.span_to_filename(callee))
             .to_string();
 
         // std lib paths are <::std::module::file type>
index 2fddea7068d961f45d14a81bb3961c1377cce7f0..7ecafa1f3ba5b90d4766902cd46f04adb729f22f 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_target::abi::LayoutOf;
+use rustc_middle::ty::layout::LayoutOf;
 
 pub fn check(
     cx: &LateContext<'_>,
index 91606ed3b2bb0d9bc83dfddb0085208451d78415..9626cf79dc129c4ba253907830fa8674c0c8e722 100644 (file)
@@ -1987,10 +1987,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
 
             // walk the return type and check for Self (this does not check associated types)
             if let Some(self_adt) = self_ty.ty_adt_def() {
-                if contains_adt_constructor(ret_ty, self_adt) {
+                if contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
                     return;
                 }
-            } else if contains_ty(ret_ty, self_ty) {
+            } else if contains_ty(cx.tcx, ret_ty, self_ty) {
                 return;
             }
 
@@ -2001,10 +2001,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl
                     if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
                         // walk the associated type and check for Self
                         if let Some(self_adt) = self_ty.ty_adt_def() {
-                            if contains_adt_constructor(projection_predicate.ty, self_adt) {
+                            if contains_adt_constructor(cx.tcx, projection_predicate.ty, self_adt) {
                                 return;
                             }
-                        } else if contains_ty(projection_predicate.ty, self_ty) {
+                        } else if contains_ty(cx.tcx, projection_predicate.ty, self_ty) {
                             return;
                         }
                     }
@@ -2053,7 +2053,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>
             if let TraitItemKind::Fn(_, _) = item.kind;
             let ret_ty = return_ty(cx, item.hir_id());
             let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty();
-            if !contains_ty(ret_ty, self_ty);
+            if !contains_ty(cx.tcx, ret_ty, self_ty);
 
             then {
                 span_lint(
index d358e9fb876a78e1a16c7b73bf29889e028143c9..940eee7a78897131d0ced058361e5dd3a87454e3 100644 (file)
@@ -122,6 +122,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
             },
             hir::ItemKind::Const(..)
             | hir::ItemKind::Enum(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Struct(..)
index 977e6d966e873779cd4d72e909278e2cbced50ea..667cdd8302528caec005ef878d7a8f2087d50e70 100644 (file)
@@ -118,6 +118,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
             },
             hir::ItemKind::Const(..)
             | hir::ItemKind::Enum(..)
+            | hir::ItemKind::Macro(..)
             | hir::ItemKind::Mod(..)
             | hir::ItemKind::Static(..)
             | hir::ItemKind::Struct(..)
index 5e559991c1697980d38fcb1798aafea3d890e2b7..90b2aa16896267b3fd66d06d739a34a202d88db4 100644 (file)
@@ -117,7 +117,7 @@ fn check_fn(
         let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
 
         let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
-            .filter(|p| !p.is_global())
+            .filter(|p| !p.is_global(cx.tcx))
             .filter_map(|obligation| {
                 // Note that we do not want to deal with qualified predicates here.
                 match obligation.predicate.kind().no_bound_vars() {
index 3f9110295fc6bcb4abe594e0fd6ec6dea2f17ee1..2a85a67fa099cac9355d26e61ca5bdada9387994 100644 (file)
@@ -187,11 +187,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D
 
     let result = cx.tcx.const_eval_resolve(
         cx.param_env,
-        ty::Unevaluated {
-            def: ty::WithOptConstParam::unknown(def_id),
-            substs,
-            promoted: None,
-        },
+        ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
         None,
     );
     is_value_unfrozen_raw(cx, result, ty)
index ac21eb5275f0f8bc443e0a88a903d0ac70e7e089..2ffc00b449d08b7e9c25282579618b98ee233912 100644 (file)
@@ -316,8 +316,11 @@ fn apply<F: for<'c> Fn(&'c mut Self)>(&mut self, f: F) {
 
 impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
     fn visit_local(&mut self, local: &'tcx Local) {
-        if let Some(ref init) = local.init {
-            self.apply(|this| walk_expr(this, &**init));
+        if let Some((init, els)) = &local.kind.init_else_opt() {
+            self.apply(|this| walk_expr(this, init));
+            if let Some(els) = els {
+                self.apply(|this| walk_block(this, els));
+            }
         }
         // add the pattern after the expression because the bindings aren't available
         // yet in the init
index 157b18c1f6b1fb8a8287c653f54827552aef5cf9..6229b9608b3cbe5aad07d6316c374f70e30f2cff 100644 (file)
 use rustc_hir::{BindingAnnotation, Body, FnDecl, HirId, Impl, ItemKind, MutTy, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span};
-use rustc_target::abi::LayoutOf;
 use rustc_target::spec::abi::Abi;
 use rustc_target::spec::Target;
 
index 530b3396abef698fd0c16baee09116f18c35f28b..f5e43264a5c69809b4dfc04d00d93b4b2f0886ee 100644 (file)
@@ -14,7 +14,7 @@
     visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
     Mutability,
 };
-use rustc_middle::ty::{self, fold::TypeVisitor, Ty};
+use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
 use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::{BytePos, Span};
@@ -576,7 +576,7 @@ fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _
                 self.possible_borrower.add(borrowed.local, lhs);
             },
             other => {
-                if ContainsRegion
+                if ContainsRegion(self.cx.tcx)
                     .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
                     .is_continue()
                 {
@@ -625,7 +625,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Loca
                 .flat_map(HybridBitSet::iter)
                 .collect();
 
-            if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
+            if ContainsRegion(self.cx.tcx).visit_ty(self.body.local_decls[*dest].ty).is_break() {
                 mutable_variables.push(*dest);
             }
 
@@ -701,12 +701,15 @@ fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _
     }
 }
 
-struct ContainsRegion;
+struct ContainsRegion<'tcx>(TyCtxt<'tcx>);
 
-impl TypeVisitor<'_> for ContainsRegion {
+impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
     type BreakTy = ();
+    fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+        Some(self.0)
+    }
 
-    fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
+    fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         ControlFlow::BREAK
     }
 }
index e153288aa58df6dce17331634af31b7bf75a36e1..681baed8c3696f0323cda6a590bea11e8b325798 100644 (file)
@@ -288,7 +288,7 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
                 .fn_sig(def_id)
                 .output()
                 .skip_binder()
-                .walk()
+                .walk(self.cx.tcx)
                 .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
         }
 
index 4472edecbed86e0642967ca0a01453043435322b..4ba5e1a0f5357829f95fad45aec80029882e8b88 100644 (file)
@@ -62,10 +62,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<
 
         // Ensure method is constructor-like
         if let Some(self_adt) = self_ty.ty_adt_def() {
-            if !contains_adt_constructor(ret_ty, self_adt) {
+            if !contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
                 return;
             }
-        } else if !contains_ty(ret_ty, self_ty) {
+        } else if !contains_ty(cx.tcx, ret_ty, self_ty) {
             return;
         }
 
index 7a444174626f47378e020cf6459a90c717c03565..e7e2016d8f2f3de1eb7c9809111036b3cf5b36f8 100644 (file)
@@ -5,9 +5,9 @@
 use rustc_errors::Applicability;
 use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::TypeFoldable;
 use rustc_span::symbol::sym;
-use rustc_target::abi::LayoutOf;
 use rustc_typeck::hir_ty_to_ty;
 
 use super::VEC_BOX;
index 6fc5707a4eeff987ad166fb277031996a5d3b6f3..97b1b2dae3c1a3d03f3bd5e051fe74396a62410c 100644 (file)
@@ -218,7 +218,7 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
 
 fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
-    matches!(ty.kind(), ty::Ref(..)) || ty.walk().any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+    matches!(ty.kind(), ty::Ref(..)) || ty.walk(cx.tcx).any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
 }
 
 impl LateLintPass<'_> for UnnecessarySortBy {
index a3601cca2eff15f7567dc688f52359ce6191278c..9ae50e47ca4c59ce899e0472b635f7d0e493a925 100644 (file)
@@ -170,7 +170,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_
                 //
                 // See also https://github.com/rust-lang/rust-clippy/issues/2894.
                 for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
-                    if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
+                    if trait_sem_ty.walk(cx.tcx).any(|inner| inner == self_ty.into()) {
                         let mut visitor = SkipTyCollector::default();
                         visitor.visit_ty(impl_hir_ty);
                         types_to_skip.extend(visitor.types_to_skip);
index 6bf216cec1670f1011e1806d653dfd48cd5af4ca..e97983a2e1451d373e77609e8f13f456f7dbbfde 100644 (file)
@@ -381,6 +381,13 @@ fn print_item(cx: &LateContext<'_>, item: &hir::Item<'_>) {
             let item_ty = cx.tcx.type_of(did);
             println!("function of type {:#?}", item_ty);
         },
+        hir::ItemKind::Macro(ref macro_def) => {
+            if macro_def.macro_rules {
+                println!("macro introduced by `macro_rules!`");
+            } else {
+                println!("macro introduced by `macro`");
+            }
+        },
         hir::ItemKind::Mod(..) => println!("module"),
         hir::ItemKind::ForeignMod { abi, .. } => println!("foreign module with abi: {}", abi),
         hir::ItemKind::GlobalAsm(asm) => println!("global asm: {:?}", asm),
index 95a45fa937f11ab8d9a7f79fa4eae96016bad9d8..e76d5f81c9640403a75295f93c55bdb7ba6c78fa 100644 (file)
@@ -1,4 +1,3 @@
-use crate::rustc_target::abi::LayoutOf;
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
@@ -8,6 +7,7 @@
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
index 2fbe27f94798b08d753b996d689f238320fad5da..8e1cd655b6111c5cb1a66d4abac0fa13deaee7b1 100644 (file)
@@ -3,10 +3,10 @@
 use if_chain::if_chain;
 use rustc_hir::{self as hir, HirId, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::layout::LayoutOf as _;
 use rustc_middle::ty::{Adt, Ty, TypeFoldable};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
-use rustc_target::abi::LayoutOf as _;
 use rustc_typeck::hir_ty_to_ty;
 
 declare_clippy_lint! {
index 7ea07a15aea51874457cee13b0319f4a8c9452db..133f6c29f7d2162d6300eca8c3d96d9f61af97d4 100644 (file)
@@ -221,7 +221,7 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool {
         (Local(l), Local(r)) => {
             eq_pat(&l.pat, &r.pat)
                 && both(&l.ty, &r.ty, |l, r| eq_ty(l, r))
-                && eq_expr_opt(&l.init, &r.init)
+                && eq_local_kind(&l.kind, &r.kind)
                 && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r))
         },
         (Item(l), Item(r)) => eq_item(l, r, eq_item_kind),
@@ -234,6 +234,16 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool {
     }
 }
 
+pub fn eq_local_kind(l: &LocalKind, r: &LocalKind) -> bool {
+    use LocalKind::*;
+    match (l, r) {
+        (Decl, Decl) => true,
+        (Init(l), Init(r)) => eq_expr(l, r),
+        (InitElse(li, le), InitElse(ri, re)) => eq_expr(li, ri) && eq_block(le, re),
+        _ => false,
+    }
+}
+
 pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> bool) -> bool {
     eq_id(l.ident, r.ident)
         && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r))
index 9ba1381da659397d6d500ba7cc1e9fbe6de28198..8bf31807d55d1441d74e503a42e29334aee365f0 100644 (file)
@@ -346,11 +346,7 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<C
                     .tcx
                     .const_eval_resolve(
                         self.param_env,
-                        ty::Unevaluated {
-                            def: ty::WithOptConstParam::unknown(def_id),
-                            substs,
-                            promoted: None,
-                        },
+                        ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
                         None,
                     )
                     .ok()
index 32a73984674adac82d7a0c2da4b4797d2e734530..ddff1686ba2ce99f9ac3f22de1abe04cd50997f8 100644 (file)
@@ -1581,7 +1581,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
         .predicates_of(did)
         .predicates
         .iter()
-        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
+        .filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None });
     traits::impossible_predicates(
         cx.tcx,
         traits::elaborate_predicates(cx.tcx, predicates)
@@ -1627,7 +1627,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
     if is_primitive {
         // if we have wrappers like Array, Slice or Tuple, print these
         // and get the type enclosed in the slice ref
-        match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
+        match expr_type.peel_refs().walk(cx.tcx).nth(1).unwrap().expect_ty().kind() {
             rustc_ty::Slice(..) => return Some("slice".into()),
             rustc_ty::Array(..) => return Some("array".into()),
             rustc_ty::Tuple(..) => return Some("tuple".into()),
@@ -1635,7 +1635,7 @@ pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<S
                 // is_recursively_primitive_type() should have taken care
                 // of the rest and we can rely on the type that is found
                 let refs_peeled = expr_type.peel_refs();
-                return Some(refs_peeled.walk().last().unwrap().to_string());
+                return Some(refs_peeled.walk(cx.tcx).last().unwrap().to_string());
             },
         }
     }
index 8e544f580665ee23d7e3d6a1322aa32b7f0f4026..e5bbf75c3b0a1857ed5b7c4580cb8e1d973ce587 100644 (file)
@@ -88,7 +88,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<&Ru
 }
 
 fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
-    for arg in ty.walk() {
+    for arg in ty.walk(tcx) {
         let ty = match arg.unpack() {
             GenericArgKind::Type(ty) => ty,
 
index a2221a0b283b0425a8d8e9f3e061f4af88edfae9..3cd8ed5aa2c8c50ef32a129d0879f5428883969f 100644 (file)
@@ -10,7 +10,7 @@
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
+use rustc_middle::ty::{self, TyCtxt, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
 use rustc_span::sym;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::DUMMY_SP;
@@ -36,8 +36,8 @@ pub fn can_partially_move_ty(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 }
 
 /// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
-pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
-    ty.walk().any(|inner| match inner.unpack() {
+pub fn contains_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool {
+    ty.walk(tcx).any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
     })
@@ -45,8 +45,8 @@ pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
 
 /// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
 /// constructor.
-pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool {
-    ty.walk().any(|inner| match inner.unpack() {
+pub fn contains_adt_constructor<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, adt: &'tcx AdtDef) -> bool {
+    ty.walk(tcx).any(|inner| match inner.unpack() {
         GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
         GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
     })
@@ -209,7 +209,7 @@ fn is_normalizable_helper<'tcx>(
                         .iter()
                         .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
                 }),
-                _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
+                _ => ty.walk(cx.tcx).all(|generic_arg| match generic_arg.unpack() {
                     GenericArgKind::Type(inner_ty) if inner_ty != ty => {
                         is_normalizable_helper(cx, param_env, inner_ty, cache)
                     },
index 31e53e846d54da5bdd0f1c29f92d4b1b6d34460e..405e3039e7d0c6f8487953b4296cb29ba075e4ac 100644 (file)
@@ -1,6 +1,3 @@
-#![feature(const_generics)]
-#![allow(incomplete_features)]
-
 pub struct ArrayWrapper<const N: usize>([usize; N]);
 
 impl<const N: usize> ArrayWrapper<{ N }> {
index 9bb2e227fc12e6ccbad119ac349f1f5af721fbcd..e3b3b27a6fc382c933c387a46ad43c98917e6ae5 100644 (file)
@@ -1,7 +1,4 @@
 // Regression test for #5233
-
-#![feature(const_generics)]
-#![allow(incomplete_features)]
 #![warn(clippy::indexing_slicing, clippy::iter_cloned_collect)]
 
 pub struct KotomineArray<T, const N: usize> {
index 8afef6b23d47653c27a9f2d2398ed411fd08667a..8b0c0f304fce0f8fc318e83f1e8d01dc90e77b1e 100644 (file)
@@ -2,7 +2,7 @@
 
 #![allow(dead_code, incomplete_features)]
 #![warn(clippy::doc_markdown)]
-#![feature(custom_inner_attributes, const_generics, const_evaluatable_checked, const_option)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
 #![rustfmt::skip]
 
 /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
@@ -203,7 +203,7 @@ fn issue_2343() {}
 /// __|_ _|__||_|
 fn pulldown_cmark_crash() {}
 
-// issue #7033 - const_evaluatable_checked ICE
+// issue #7033 - generic_const_exprs ICE
 struct S<T, const N: usize>
 where [(); N.checked_next_power_of_two().unwrap()]: {
     arr: [T; N.checked_next_power_of_two().unwrap()],
index e48451acfe8f5f4c67f76c65298e40b9a463e9f5..7752a8a6ff2b4094a3089d3295d77b4d2a44f597 100644 (file)
@@ -106,24 +106,6 @@ LL |         1 => 2,
    |         ^
    = help: ...or consider changing the match arm bodies
 
-error: this `match` has identical arm bodies
-  --> $DIR/match_same_arms.rs:33:14
-   |
-LL |         3 => 2, //~ ERROR 3rd matched arms have same body
-   |              ^
-   |
-note: same as this
-  --> $DIR/match_same_arms.rs:32:14
-   |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
-   |              ^
-help: consider refactoring into `2 | 3`
-  --> $DIR/match_same_arms.rs:32:9
-   |
-LL |         2 => 2, //~ ERROR 2nd matched arms have same body
-   |         ^
-   = help: ...or consider changing the match arm bodies
-
 error: this `match` has identical arm bodies
   --> $DIR/match_same_arms.rs:50:55
    |
@@ -142,5 +124,5 @@ LL |                 CommandInfo::BuiltIn { name, .. } => name.to_string(),
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: ...or consider changing the match arm bodies
 
-error: aborting due to 8 previous errors
+error: aborting due to 7 previous errors
 
index 6d2cbb6ad96fa865870159854b8e1d053d6f0b75..aa60d0504e5e60c1181351c9444736b62d740b5a 100644 (file)
@@ -5,8 +5,7 @@
 // aux-build:helper.rs
 
 #![warn(clippy::missing_const_for_fn)]
-#![allow(incomplete_features)]
-#![feature(start, const_generics)]
+#![feature(start)]
 #![feature(custom_inner_attributes)]
 
 extern crate helper;
index 0accb516f5f6b4a145e161c708cc726a72b221a8..baa7eec05462ebad8baea0762ed76b51ae7dfa2d 100644 (file)
@@ -1,6 +1,5 @@
 #![warn(clippy::missing_const_for_fn)]
 #![allow(incomplete_features, clippy::let_and_return)]
-#![feature(const_generics)]
 #![feature(custom_inner_attributes)]
 
 use std::mem::transmute;
index 63c211f39fa1e3530a1be0d041f69d6bae65ee63..b89cc6451bb592c5f3f6fbbab1daa194953d5101 100644 (file)
@@ -1,5 +1,5 @@
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:14:5
+  --> $DIR/could_be_const.rs:13:5
    |
 LL | /     pub fn new() -> Self {
 LL | |         Self { guess: 42 }
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::missing-const-for-fn` implied by `-D warnings`
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:18:5
+  --> $DIR/could_be_const.rs:17:5
    |
 LL | /     fn const_generic_params<'a, T, const N: usize>(&self, b: &'a [T; N]) -> &'a [T; N] {
 LL | |         b
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:24:1
+  --> $DIR/could_be_const.rs:23:1
    |
 LL | / fn one() -> i32 {
 LL | |     1
@@ -25,7 +25,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:29:1
+  --> $DIR/could_be_const.rs:28:1
    |
 LL | / fn two() -> i32 {
 LL | |     let abc = 2;
@@ -34,7 +34,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:35:1
+  --> $DIR/could_be_const.rs:34:1
    |
 LL | / fn string() -> String {
 LL | |     String::new()
@@ -42,7 +42,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:40:1
+  --> $DIR/could_be_const.rs:39:1
    |
 LL | / unsafe fn four() -> i32 {
 LL | |     4
@@ -50,7 +50,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:45:1
+  --> $DIR/could_be_const.rs:44:1
    |
 LL | / fn generic<T>(t: T) -> T {
 LL | |     t
@@ -58,7 +58,7 @@ LL | | }
    | |_^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:68:9
+  --> $DIR/could_be_const.rs:67:9
    |
 LL | /         pub fn b(self, a: &A) -> B {
 LL | |             B
@@ -66,7 +66,7 @@ LL | |         }
    | |_________^
 
 error: this could be a `const fn`
-  --> $DIR/could_be_const.rs:78:5
+  --> $DIR/could_be_const.rs:77:5
    |
 LL | /     fn const_fn_stabilized_before_msrv(byte: u8) {
 LL | |         byte.is_ascii_digit();
index 2b2c699733852dd464507708dc41ad79a15b92eb..34f762bbb923648996cb56af20e84dba18b4fb47 100644 (file)
@@ -46,12 +46,6 @@ LL |     const ONE: u32 = 1 * 1;
    |
    = note: `-D clippy::identity-op` implied by `-D warnings`
 
-error: the operation is ineffective. Consider reducing it to `1`
-  --> $DIR/modulo_one.rs:13:22
-   |
-LL |     const ONE: u32 = 1 * 1;
-   |                      ^^^^^
-
 error: any number modulo 1 will be 0
   --> $DIR/modulo_one.rs:17:5
    |
@@ -70,5 +64,5 @@ error: any number modulo -1 will panic/overflow or result in 0
 LL |     INT_MIN % NEG_ONE; // also caught by rustc
    |     ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
index 96065699d321a057f9a8e28bf07ad3e4551ee282..dd6f2f6641d678b14b1d401fac951d98ce43f913 100644 (file)
@@ -6,12 +6,6 @@ LL |         self.x == other.y && self.y == other.y && self.z == other.z
    |
    = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
 
-error: this sequence of operators looks suspiciously like a bug
-  --> $DIR/suspicious_operation_groupings.rs:14:9
-   |
-LL |         self.x == other.y && self.y == other.y && self.z == other.z
-   |         ^^^^^^^^^^^^^^^^^ help: did you mean: `self.x == other.x`
-
 error: this sequence of operators looks suspiciously like a bug
   --> $DIR/suspicious_operation_groupings.rs:27:20
    |
@@ -162,5 +156,5 @@ error: this sequence of operators looks suspiciously like a bug
 LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
    |                           ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b`
 
-error: aborting due to 27 previous errors
+error: aborting due to 26 previous errors
 
index f291918225f450e21b6914ffc7f7afeab7e639ee..51a4d74109a639181ee8d1087a7f7e631947728d 100644 (file)
@@ -3227,7 +3227,7 @@ fn load_compare_outputs(
                 // so it needs to be removed when comparing the run-pass test execution output
                 lazy_static! {
                     static ref REMOTE_TEST_RE: Regex = Regex::new(
-                        "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-]+)+\", waiting for result\n"
+                        "^uploaded \"\\$TEST_BUILD_DIR(/[[:alnum:]_\\-.]+)+\", waiting for result\n"
                     )
                     .unwrap();
                 }
index 042cbf175bfdad6524fd00d7570b2297a0426063..09cadcbb62a3529801d0463d9878db3f0b5060c7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 042cbf175bfdad6524fd00d7570b2297a0426063
+Subproject commit 09cadcbb62a3529801d0463d9878db3f0b5060c7
index c9d46aef294a0df562df28960531048d9a431c66..34d73a77fd3d4fa6b41c5a7737b316865febcb13 100644 (file)
@@ -160,6 +160,7 @@ fn rewrite_closure_with_block(
             .first()
             .map(|attr| attr.span.to(body.span))
             .unwrap_or(body.span),
+        could_be_bare_literal: false,
     };
     let block = crate::expr::rewrite_block_with_visitor(
         context,
index 0542358c6e7c5ebb40e15055364449df2caae79c..2483d0570d9eaf1c27358646918b8bd56c50bfcb 100644 (file)
@@ -48,7 +48,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
         skip_out_of_file_lines_range!(context, self.span);
 
-        if contains_skip(&self.attrs) {
+        if contains_skip(&self.attrs) || matches!(self.kind, ast::LocalKind::InitElse(..)) {
             return None;
         }
 
@@ -97,7 +97,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                 infix.push_str(&rewrite);
             }
 
-            if self.init.is_some() {
+            if self.kind.init().is_some() {
                 infix.push_str(" =");
             }
 
@@ -106,11 +106,12 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
 
         result.push_str(&infix);
 
-        if let Some(ref ex) = self.init {
+        if let Some((init, _els)) = self.kind.init_else_opt() {
             // 1 = trailing semicolon;
             let nested_shape = shape.sub_width(1)?;
 
-            result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?;
+            result = rewrite_assign_rhs(context, result, init, nested_shape)?;
+            // todo else
         }
 
         result.push(';');
index 870f0acfe395c527bd0e0a6fee9c833073e766ba..2965b0928aadaf751663bad5017ecfbf93101057 100644 (file)
@@ -311,6 +311,7 @@ fn build_diagnostic(level: DiagnosticLevel, span: Option<MultiSpan>) -> Diagnost
                 suggestions: vec![],
                 span: span.unwrap_or_else(MultiSpan::new),
                 sort_span: DUMMY_SP,
+                is_lint: false,
             }
         }
 
index c6f89c310650c93306adca00625e6e117f70bfcc..640d127e8609818052a0024ad2aa8f604b215066 100644 (file)
@@ -537,10 +537,10 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
                         .map(|s| format!("?{}", s)),
                     ast::TraitBoundModifier::MaybeConst => poly_trait_ref
                         .rewrite(context, shape.offset_left(7)?)
-                        .map(|s| format!("?const {}", s)),
+                        .map(|s| format!("~const {}", s)),
                     ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref
                         .rewrite(context, shape.offset_left(8)?)
-                        .map(|s| format!("?const ?{}", s)),
+                        .map(|s| format!("~const ?{}", s)),
                 };
                 rewrite.map(|s| if has_paren { format!("({})", s) } else { s })
             }
diff --git a/src/tools/rustfmt/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs
new file mode 100644 (file)
index 0000000..a6e816f
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    let Some(1) = Some(1) else { return };
+}
index 57f31dc901e77d0dcb02a69b24405574bc351d4a..61ef73a3cab1c6dbe80399e0f4fc5c0f77ae6685 100644 (file)
@@ -140,29 +140,23 @@ fn foo(a: SomeLongComplexType, b: SomeOtherLongComplexType) -> Box<Future<Item =
 
 type MyFn = fn(a: SomeLongComplexType, b: SomeOtherLongComplexType,) -> Box<Future<Item = AnotherLongType, Error = ALongErrorType>>;
 
-// Const opt-out
+// Const bound
 
-trait T: ?   const  Super {}
+trait T: ~   const  Super {}
 
-const fn maybe_const<S: ?   const    T>() -> i32 { <S as T>::CONST }
+const fn not_quite_const<S: ~  const    T>() -> i32 { <S as T>::CONST }
 
-struct S<T:?  const   ?  Sized>(std::marker::PhantomData<T>);
+struct S<T:~  const   ?  Sized>(std::marker::PhantomData<T>);
 
-impl ?    const T {}
+impl ~    const T {}
 
-fn trait_object() -> &'static dyn ?  const T { &S }
+fn apit(_: impl ~   const T) {}
 
-fn i(_: impl IntoIterator<Item = Box<dyn ?    const    T>>) {}
-
-fn apit(_: impl ?const T) {}
-
-fn rpit() -> impl ?  const T { S }
+fn rpit() -> impl ~  const T { S }
 
 pub struct Foo<T: Trait>(T);
-impl<T:   ?  const Trait> Foo<T> {
+impl<T:   ~  const Trait> Foo<T> {
     fn new(t: T) -> Self {
-        // not calling methods on `t`, so we opt out of requiring
-        // `<T as Trait>` to have const methods via `?const`
         Self(t)
     }
 }
@@ -171,4 +165,4 @@ fn new(t: T) -> Self {
 type T = typeof(
 1);
 impl T for  .. {
-}
\ No newline at end of file
+}
diff --git a/src/tools/rustfmt/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs
new file mode 100644 (file)
index 0000000..a6e816f
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    let Some(1) = Some(1) else { return };
+}
index e7761251688a9f31e86b6860171a7482203ca4e4..38cf909c2587a52c0b4b452df0cf6a79400d8270 100644 (file)
@@ -145,35 +145,27 @@ fn foo(
     b: SomeOtherLongComplexType,
 ) -> Box<Future<Item = AnotherLongType, Error = ALongErrorType>>;
 
-// Const opt-out
+// Const bound
 
-trait T: ?const Super {}
+trait T: ~const Super {}
 
-const fn maybe_const<S: ?const T>() -> i32 {
+const fn not_quite_const<S: ~const T>() -> i32 {
     <S as T>::CONST
 }
 
-struct S<T: ?const ?Sized>(std::marker::PhantomData<T>);
+struct S<T: ~const ?Sized>(std::marker::PhantomData<T>);
 
-impl ?const T {}
+impl ~const T {}
 
-fn trait_object() -> &'static dyn ?const T {
-    &S
-}
-
-fn i(_: impl IntoIterator<Item = Box<dyn ?const T>>) {}
-
-fn apit(_: impl ?const T) {}
+fn apit(_: impl ~const T) {}
 
-fn rpit() -> impl ?const T {
+fn rpit() -> impl ~const T {
     S
 }
 
 pub struct Foo<T: Trait>(T);
-impl<T: ?const Trait> Foo<T> {
+impl<T: ~const Trait> Foo<T> {
     fn new(t: T) -> Self {
-        // not calling methods on `t`, so we opt out of requiring
-        // `<T as Trait>` to have const methods via `?const`
         Self(t)
     }
 }
index 3ebf789f5a8dfa4d1d653d65a125a99a50b3294c..373aea97570a799f495d563956060f172be596a1 100644 (file)
@@ -1 +1 @@
-1.56.0
+1.57.0
index 81c6719647fc1476ff7bf3d2bbc5ddb9e154f8aa..1e4df4d3fb79a58185907d63c0574bdeb779ec16 100644 (file)
@@ -102,6 +102,8 @@ message_on_add = """\
 - Needs `I-nominated`?
 """
 message_on_remove = "Issue #{number}'s prioritization request has been removed."
+message_on_close = "Issue #{number} has been closed while requested for prioritization."
+message_on_reopen = "Issue #{number} has been reopened."
 
 [notify-zulip."T-rustdoc"]
 required_labels = ["I-nominated"]