]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #88846 - jackh726:issue-88360, r=nikomatsakis
authorbors <bors@rust-lang.org>
Wed, 22 Sep 2021 04:02:01 +0000 (04:02 +0000)
committerbors <bors@rust-lang.org>
Wed, 22 Sep 2021 04:02:01 +0000 (04:02 +0000)
In suggest_missing_return_type, erase late bound regions after normalizing

Fixes #88360

There might be some hardening that could be done to not error or avoid erroring with LUBing `ReErased` with `ReEmpty`, but this was the most simple fix for this particular case.

r? `@nikomatsakis`

1148 files changed:
.github/workflows/ci.yml
Cargo.lock
compiler/rustc/Cargo.toml
compiler/rustc_apfloat/Cargo.toml
compiler/rustc_arena/Cargo.toml
compiler/rustc_ast/Cargo.toml
compiler/rustc_ast/src/ast.rs
compiler/rustc_ast/src/attr/mod.rs
compiler/rustc_ast/src/mut_visit.rs
compiler/rustc_ast/src/visit.rs
compiler/rustc_ast_lowering/Cargo.toml
compiler/rustc_ast_lowering/src/block.rs
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/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/Cargo.toml
compiler/rustc_ast_pretty/src/pprust/state.rs
compiler/rustc_attr/Cargo.toml
compiler/rustc_borrowck/Cargo.toml
compiler/rustc_borrowck/src/consumers.rs
compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
compiler/rustc_borrowck/src/diagnostics/move_errors.rs
compiler/rustc_borrowck/src/diagnostics/region_errors.rs
compiler/rustc_borrowck/src/lib.rs
compiler/rustc_borrowck/src/nll.rs
compiler/rustc_borrowck/src/region_infer/mod.rs
compiler/rustc_borrowck/src/region_infer/opaque_types.rs
compiler/rustc_borrowck/src/type_check/canonical.rs
compiler/rustc_borrowck/src/type_check/free_region_relations.rs
compiler/rustc_borrowck/src/type_check/input_output.rs
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_borrowck/src/type_check/relate_tys.rs
compiler/rustc_builtin_macros/Cargo.toml
compiler/rustc_builtin_macros/src/asm.rs
compiler/rustc_builtin_macros/src/deriving/debug.rs
compiler/rustc_builtin_macros/src/format.rs
compiler/rustc_codegen_cranelift/Cargo.toml
compiler/rustc_codegen_cranelift/src/abi/mod.rs
compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
compiler/rustc_codegen_cranelift/src/base.rs
compiler/rustc_codegen_cranelift/src/bin/cg_clif_build_sysroot.rs
compiler/rustc_codegen_cranelift/src/common.rs
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
compiler/rustc_codegen_cranelift/src/pretty_clif.rs
compiler/rustc_codegen_cranelift/src/value_and_place.rs
compiler/rustc_codegen_llvm/Cargo.toml
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/asm.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/builder.rs
compiler/rustc_codegen_llvm/src/callee.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/coverageinfo/mod.rs
compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
compiler/rustc_codegen_llvm/src/intrinsic.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_ssa/Cargo.toml
compiler/rustc_codegen_ssa/src/back/link.rs
compiler/rustc_codegen_ssa/src/back/linker.rs
compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
compiler/rustc_codegen_ssa/src/mir/block.rs
compiler/rustc_codegen_ssa/src/mir/constant.rs
compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
compiler/rustc_codegen_ssa/src/mir/intrinsic.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/traits/backend.rs
compiler/rustc_codegen_ssa/src/traits/builder.rs
compiler/rustc_codegen_ssa/src/traits/consts.rs
compiler/rustc_const_eval/Cargo.toml
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/fn_queries.rs
compiler/rustc_const_eval/src/const_eval/machine.rs
compiler/rustc_const_eval/src/interpret/intrinsics.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_const_eval/src/interpret/terminator.rs
compiler/rustc_const_eval/src/interpret/validity.rs
compiler/rustc_const_eval/src/transform/check_consts/check.rs
compiler/rustc_const_eval/src/transform/check_consts/mod.rs
compiler/rustc_const_eval/src/transform/check_consts/ops.rs
compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_const_eval/src/transform/validate.rs
compiler/rustc_data_structures/Cargo.toml
compiler/rustc_data_structures/src/graph/iterate/mod.rs
compiler/rustc_data_structures/src/graph/iterate/tests.rs
compiler/rustc_data_structures/src/graph/mod.rs
compiler/rustc_data_structures/src/lib.rs
compiler/rustc_data_structures/src/sharded.rs
compiler/rustc_data_structures/src/stable_hasher.rs
compiler/rustc_driver/Cargo.toml
compiler/rustc_driver/src/lib.rs
compiler/rustc_error_codes/Cargo.toml
compiler/rustc_error_codes/src/error_codes/E0071.md
compiler/rustc_error_codes/src/error_codes/E0439.md
compiler/rustc_errors/Cargo.toml
compiler/rustc_errors/src/diagnostic.rs
compiler/rustc_errors/src/diagnostic_builder.rs
compiler/rustc_errors/src/lib.rs
compiler/rustc_expand/Cargo.toml
compiler/rustc_expand/src/base.rs
compiler/rustc_expand/src/expand.rs
compiler/rustc_expand/src/mbe/quoted.rs
compiler/rustc_expand/src/proc_macro_server.rs
compiler/rustc_feature/Cargo.toml
compiler/rustc_feature/src/accepted.rs
compiler/rustc_feature/src/active.rs
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_feature/src/lib.rs
compiler/rustc_feature/src/removed.rs
compiler/rustc_fs_util/Cargo.toml
compiler/rustc_graphviz/Cargo.toml
compiler/rustc_hir/Cargo.toml
compiler/rustc_hir/src/arena.rs
compiler/rustc_hir/src/def.rs
compiler/rustc_hir/src/def_path_hash_map.rs [new file with mode: 0644]
compiler/rustc_hir/src/definitions.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir/src/lang_items.rs
compiler/rustc_hir/src/lib.rs
compiler/rustc_hir_pretty/Cargo.toml
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_incremental/Cargo.toml
compiler/rustc_index/Cargo.toml
compiler/rustc_infer/Cargo.toml
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
compiler/rustc_infer/src/infer/error_reporting/note.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_infer/src/infer/nll_relate/mod.rs
compiler/rustc_infer/src/infer/projection.rs [new file with mode: 0644]
compiler/rustc_infer/src/traits/error_reporting/mod.rs
compiler/rustc_infer/src/traits/mod.rs
compiler/rustc_infer/src/traits/project.rs
compiler/rustc_interface/Cargo.toml
compiler/rustc_interface/src/callbacks.rs
compiler/rustc_interface/src/passes.rs
compiler/rustc_interface/src/tests.rs
compiler/rustc_interface/src/util.rs
compiler/rustc_lexer/Cargo.toml
compiler/rustc_lint/Cargo.toml
compiler/rustc_lint/src/array_into_iter.rs
compiler/rustc_lint/src/builtin.rs
compiler/rustc_lint/src/late.rs
compiler/rustc_lint/src/non_fmt_panic.rs
compiler/rustc_lint/src/traits.rs
compiler/rustc_lint/src/types.rs
compiler/rustc_lint/src/unused.rs
compiler/rustc_lint_defs/Cargo.toml
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_llvm/Cargo.toml
compiler/rustc_llvm/build.rs
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_llvm/src/lib.rs
compiler/rustc_macros/Cargo.toml
compiler/rustc_macros/src/session_diagnostic.rs
compiler/rustc_macros/src/symbols.rs
compiler/rustc_metadata/Cargo.toml
compiler/rustc_metadata/src/creader.rs
compiler/rustc_metadata/src/dependency_format.rs
compiler/rustc_metadata/src/locator.rs
compiler/rustc_metadata/src/native_libs.rs
compiler/rustc_metadata/src/rmeta/decoder.rs
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs [new file with mode: 0644]
compiler/rustc_metadata/src/rmeta/encoder.rs
compiler/rustc_metadata/src/rmeta/mod.rs
compiler/rustc_metadata/src/rmeta/table.rs
compiler/rustc_middle/Cargo.toml
compiler/rustc_middle/src/arena.rs
compiler/rustc_middle/src/dep_graph/dep_node.rs
compiler/rustc_middle/src/dep_graph/mod.rs
compiler/rustc_middle/src/hir/exports.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/ich/hcx.rs
compiler/rustc_middle/src/ich/impls_ty.rs
compiler/rustc_middle/src/lib.rs
compiler/rustc_middle/src/middle/cstore.rs
compiler/rustc_middle/src/middle/region.rs
compiler/rustc_middle/src/mir/abstract_const.rs [deleted file]
compiler/rustc_middle/src/mir/interpret/pointer.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/query.rs
compiler/rustc_middle/src/mir/tcx.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/thir.rs
compiler/rustc_middle/src/thir/abstract_const.rs [new file with mode: 0644]
compiler/rustc_middle/src/thir/visit.rs [new file with mode: 0644]
compiler/rustc_middle/src/traits/mod.rs
compiler/rustc_middle/src/traits/select.rs
compiler/rustc_middle/src/traits/structural_impls.rs
compiler/rustc_middle/src/ty/adt.rs
compiler/rustc_middle/src/ty/codec.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/error.rs
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/query.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_middle/src/ty/util.rs
compiler/rustc_mir_build/Cargo.toml
compiler/rustc_mir_build/src/build/expr/as_operand.rs
compiler/rustc_mir_build/src/build/expr/as_rvalue.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/simplify.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/build/scope.rs
compiler/rustc_mir_build/src/check_unsafety.rs
compiler/rustc_mir_build/src/thir/mod.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/deconstruct_pat.rs
compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
compiler/rustc_mir_build/src/thir/visit.rs [deleted file]
compiler/rustc_mir_dataflow/Cargo.toml
compiler/rustc_mir_dataflow/src/lib.rs
compiler/rustc_mir_dataflow/src/move_paths/builder.rs
compiler/rustc_mir_transform/Cargo.toml
compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
compiler/rustc_mir_transform/src/coverage/mod.rs
compiler/rustc_mir_transform/src/coverage/spans.rs
compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/lower_intrinsics.rs
compiler/rustc_mir_transform/src/lower_slice_len.rs
compiler/rustc_mir_transform/src/remove_zsts.rs
compiler/rustc_mir_transform/src/simplify.rs
compiler/rustc_monomorphize/Cargo.toml
compiler/rustc_monomorphize/src/polymorphize.rs
compiler/rustc_parse/Cargo.toml
compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
compiler/rustc_parse/src/lib.rs
compiler/rustc_parse/src/parser/attr_wrapper.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/stmt.rs
compiler/rustc_parse/src/parser/ty.rs
compiler/rustc_parse_format/Cargo.toml
compiler/rustc_passes/Cargo.toml
compiler/rustc_passes/src/dead.rs
compiler/rustc_passes/src/hir_id_validator.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/region.rs
compiler/rustc_passes/src/stability.rs
compiler/rustc_plugin_impl/Cargo.toml
compiler/rustc_privacy/Cargo.toml
compiler/rustc_privacy/src/lib.rs
compiler/rustc_query_impl/Cargo.toml
compiler/rustc_query_impl/src/keys.rs
compiler/rustc_query_impl/src/on_disk_cache.rs
compiler/rustc_query_system/Cargo.toml
compiler/rustc_query_system/src/dep_graph/dep_node.rs
compiler/rustc_query_system/src/dep_graph/graph.rs
compiler/rustc_query_system/src/dep_graph/mod.rs
compiler/rustc_query_system/src/dep_graph/serialized.rs
compiler/rustc_query_system/src/query/job.rs
compiler/rustc_query_system/src/query/plumbing.rs
compiler/rustc_resolve/Cargo.toml
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/def_collector.rs
compiler/rustc_resolve/src/imports.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/Cargo.toml
compiler/rustc_serialize/Cargo.toml
compiler/rustc_serialize/src/serialize.rs
compiler/rustc_session/Cargo.toml
compiler/rustc_session/src/config.rs
compiler/rustc_session/src/filesearch.rs
compiler/rustc_session/src/options.rs
compiler/rustc_session/src/search_paths.rs
compiler/rustc_session/src/session.rs
compiler/rustc_span/Cargo.toml
compiler/rustc_span/src/caching_source_map_view.rs
compiler/rustc_span/src/hygiene.rs
compiler/rustc_span/src/lib.rs
compiler/rustc_span/src/source_map.rs
compiler/rustc_span/src/span_encoding.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_span/src/symbol/tests.rs
compiler/rustc_symbol_mangling/Cargo.toml
compiler/rustc_target/Cargo.toml
compiler/rustc_target/src/abi/call/m68k.rs [new file with mode: 0644]
compiler/rustc_target/src/abi/call/mips64.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/abi/call/riscv.rs
compiler/rustc_target/src/abi/call/s390x.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/spec/armv6k_nintendo_3ds.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs [new file with mode: 0644]
compiler/rustc_target/src/spec/mod.rs
compiler/rustc_trait_selection/Cargo.toml
compiler/rustc_trait_selection/src/infer.rs
compiler/rustc_trait_selection/src/opaque_types.rs
compiler/rustc_trait_selection/src/traits/chalk_fulfill.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/on_unimplemented.rs
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/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/select/candidate_assembly.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/specialize/specialization_graph.rs
compiler/rustc_trait_selection/src/traits/wf.rs
compiler/rustc_traits/Cargo.toml
compiler/rustc_ty_utils/Cargo.toml
compiler/rustc_ty_utils/src/instance.rs
compiler/rustc_ty_utils/src/needs_drop.rs
compiler/rustc_ty_utils/src/ty.rs
compiler/rustc_type_ir/Cargo.toml
compiler/rustc_typeck/Cargo.toml
compiler/rustc_typeck/src/astconv/mod.rs
compiler/rustc_typeck/src/check/callee.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/demand.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
compiler/rustc_typeck/src/check/intrinsic.rs
compiler/rustc_typeck/src/check/method/mod.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/wfcheck.rs
compiler/rustc_typeck/src/coherence/inherent_impls.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/errors.rs
compiler/rustc_typeck/src/impl_wf_check.rs
compiler/rustc_typeck/src/lib.rs
compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
config.toml.example
library/alloc/src/borrow.rs
library/alloc/src/collections/vec_deque/into_iter.rs
library/alloc/src/collections/vec_deque/mod.rs
library/alloc/tests/lib.rs
library/backtrace
library/core/primitive_docs/box_into_raw.md [new file with mode: 0644]
library/core/primitive_docs/fs_file.md [new file with mode: 0644]
library/core/primitive_docs/io_bufread.md [new file with mode: 0644]
library/core/primitive_docs/io_read.md [new file with mode: 0644]
library/core/primitive_docs/io_seek.md [new file with mode: 0644]
library/core/primitive_docs/io_write.md [new file with mode: 0644]
library/core/primitive_docs/net_tosocketaddrs.md [new file with mode: 0644]
library/core/primitive_docs/process_exit.md [new file with mode: 0644]
library/core/primitive_docs/string_string.md [new file with mode: 0644]
library/core/src/ascii.rs
library/core/src/bool.rs
library/core/src/cell.rs
library/core/src/char/methods.rs
library/core/src/clone.rs
library/core/src/fmt/mod.rs
library/core/src/iter/adapters/map_while.rs
library/core/src/iter/adapters/mod.rs
library/core/src/iter/mod.rs
library/core/src/iter/traits/iterator.rs
library/core/src/lazy.rs
library/core/src/lib.rs
library/core/src/marker.rs
library/core/src/mem/manually_drop.rs
library/core/src/num/wrapping.rs
library/core/src/ops/deref.rs
library/core/src/panic.rs
library/core/src/panicking.rs
library/core/src/primitive_docs.rs [new file with mode: 0644]
library/core/src/slice/mod.rs
library/core/tests/fmt/builders.rs
library/core/tests/lib.rs
library/proc_macro/src/bridge/mod.rs
library/proc_macro/src/lib.rs
library/std/primitive_docs/box_into_raw.md [new file with mode: 0644]
library/std/primitive_docs/fs_file.md [new file with mode: 0644]
library/std/primitive_docs/io_bufread.md [new file with mode: 0644]
library/std/primitive_docs/io_read.md [new file with mode: 0644]
library/std/primitive_docs/io_seek.md [new file with mode: 0644]
library/std/primitive_docs/io_write.md [new file with mode: 0644]
library/std/primitive_docs/net_tosocketaddrs.md [new file with mode: 0644]
library/std/primitive_docs/process_exit.md [new file with mode: 0644]
library/std/primitive_docs/string_string.md [new file with mode: 0644]
library/std/src/collections/mod.rs
library/std/src/env.rs
library/std/src/error.rs
library/std/src/ffi/c_str.rs
library/std/src/io/buffered/tests.rs
library/std/src/io/mod.rs
library/std/src/keyword_docs.rs
library/std/src/lib.rs
library/std/src/net/tcp.rs
library/std/src/os/linux/fs.rs
library/std/src/os/linux/process.rs
library/std/src/os/linux/raw.rs
library/std/src/os/mod.rs
library/std/src/os/raw/char.md
library/std/src/os/unix/ffi/mod.rs
library/std/src/os/unix/fs.rs
library/std/src/os/unix/mod.rs
library/std/src/os/unix/net/mod.rs
library/std/src/os/unix/process.rs
library/std/src/os/unix/thread.rs
library/std/src/os/wasi/ffi.rs
library/std/src/os/wasi/fs.rs
library/std/src/os/wasi/mod.rs
library/std/src/os/windows/ffi.rs
library/std/src/os/windows/fs.rs
library/std/src/os/windows/mod.rs
library/std/src/os/windows/process.rs
library/std/src/os/windows/thread.rs
library/std/src/panic.rs
library/std/src/primitive_docs.rs
library/std/src/rt.rs
library/std/src/sys/unix/fs.rs
library/std/src/time.rs
library/std/src/time/monotonic.rs
library/test/src/formatters/junit.rs
library/test/src/term/terminfo/mod.rs
src/bootstrap/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/test.rs
src/build_helper/Cargo.toml
src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile [new file with mode: 0644]
src/ci/github-actions/ci.yml
src/ci/scripts/install-clang.sh
src/ci/scripts/verify-backported-commits.sh
src/doc/embedded-book
src/doc/rust-by-example
src/doc/rustc-dev-guide
src/doc/rustc/src/platform-support.md
src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md [new file with mode: 0644]
src/doc/rustdoc/src/unstable-features.md
src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md [new file with mode: 0644]
src/doc/unstable-book/src/library-features/asm.md
src/etc/test-float-parse/Cargo.toml
src/librustdoc/Cargo.toml
src/librustdoc/clean/blanket_impl.rs
src/librustdoc/clean/cfg.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/clean/utils.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/docfs.rs
src/librustdoc/doctest.rs
src/librustdoc/doctest/tests.rs
src/librustdoc/formats/cache.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.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/rustdoc.css
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/librustdoc/html/static/js/main.js
src/librustdoc/json/conversions.rs
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/passes/bare_urls.rs
src/librustdoc/passes/calculate_doc_coverage.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/doc_test_lints.rs
src/librustdoc/passes/html_tags.rs
src/librustdoc/visit_lib.rs
src/llvm-project
src/rustdoc-json-types/Cargo.toml
src/test/assembly/niche-prefer-zero.rs [new file with mode: 0644]
src/test/assembly/x86_64-sse_crc.rs [new file with mode: 0644]
src/test/codegen/panic-in-drop-abort.rs [new file with mode: 0644]
src/test/codegen/sse42-implies-crc32.rs [new file with mode: 0644]
src/test/debuginfo/basic-types.rs
src/test/debuginfo/msvc-pretty-enums.rs
src/test/debuginfo/msvc-scalarpair-params.rs [new file with mode: 0644]
src/test/debuginfo/mutex.rs
src/test/debuginfo/pretty-std.rs
src/test/incremental/change_symbol_export_status.rs
src/test/incremental/hashes/call_expressions.rs
src/test/incremental/hashes/closure_expressions.rs
src/test/incremental/hashes/consts.rs
src/test/incremental/hashes/enum_constructors.rs
src/test/incremental/hashes/enum_defs.rs
src/test/incremental/hashes/exported_vs_not.rs
src/test/incremental/hashes/extern_mods.rs
src/test/incremental/hashes/for_loops.rs
src/test/incremental/hashes/function_interfaces.rs
src/test/incremental/hashes/if_expressions.rs
src/test/incremental/hashes/indexing_expressions.rs
src/test/incremental/hashes/inherent_impls.rs
src/test/incremental/hashes/inline_asm.rs
src/test/incremental/hashes/let_expressions.rs
src/test/incremental/hashes/loop_expressions.rs
src/test/incremental/hashes/match_expressions.rs
src/test/incremental/hashes/statics.rs
src/test/incremental/hashes/struct_constructors.rs
src/test/incremental/hashes/struct_defs.rs
src/test/incremental/hashes/trait_defs.rs
src/test/incremental/hashes/trait_impls.rs
src/test/incremental/hashes/type_defs.rs
src/test/incremental/hashes/unary_and_binary_exprs.rs
src/test/incremental/hashes/while_let_loops.rs
src/test/incremental/hashes/while_loops.rs
src/test/incremental/spans_significant_w_debuginfo.rs
src/test/incremental/spans_significant_w_panic.rs
src/test/incremental/string_constant.rs
src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
src/test/mir-opt/inline/inline_diverging.h.Inline.diff
src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff [new file with mode: 0644]
src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
src/test/mir-opt/lower_intrinsics.rs
src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.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/while_storage.while_loop.PreCodegen.after.mir
src/test/pretty/anonymous-types.rs [deleted file]
src/test/run-make-fulldeps/reproducible-build/Makefile
src/test/run-make-fulldeps/sysroot-crates-are-unstable/test.py
src/test/rustdoc-gui/code-sidebar-toggle.goml
src/test/rustdoc-gui/docblock-table-overflow.goml
src/test/rustdoc-gui/jump-to-def-background.goml [new file with mode: 0644]
src/test/rustdoc-gui/src/lib2/lib.rs
src/test/rustdoc-gui/src/link_to_definition/Cargo.lock [new file with mode: 0644]
src/test/rustdoc-gui/src/link_to_definition/Cargo.toml [new file with mode: 0644]
src/test/rustdoc-gui/src/link_to_definition/lib.rs [new file with mode: 0644]
src/test/rustdoc-js-std/multi-query.js
src/test/rustdoc-ui/coverage/enum-tuple-documented.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout [new file with mode: 0644]
src/test/rustdoc-ui/coverage/enum-tuple.rs [new file with mode: 0644]
src/test/rustdoc-ui/coverage/enum-tuple.stdout [new file with mode: 0644]
src/test/rustdoc-ui/coverage/enums.stdout
src/test/rustdoc-ui/display-output.rs [new file with mode: 0644]
src/test/rustdoc-ui/display-output.stdout [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc/anchors.rs
src/test/rustdoc-ui/intra-doc/anchors.stderr
src/test/rustdoc-ui/invalid-syntax.stderr
src/test/rustdoc-ui/lint-missing-doc-code-example.rs
src/test/rustdoc/auxiliary/issue-15318.rs
src/test/rustdoc/auxiliary/primitive-doc.rs
src/test/rustdoc/check-source-code-urls-to-def-std.rs [new file with mode: 0644]
src/test/rustdoc/check-source-code-urls-to-def.rs
src/test/rustdoc/cross-crate-primitive-doc.rs
src/test/rustdoc/intra-doc/anchors.rs
src/test/rustdoc/intra-doc/auxiliary/my-core.rs
src/test/rustdoc/intra-doc/prim-methods-external-core.rs
src/test/rustdoc/intra-doc/prim-methods-local.rs
src/test/rustdoc/intra-link-prim-self.rs
src/test/rustdoc/issue-15318-2.rs
src/test/rustdoc/issue-88600.rs [new file with mode: 0644]
src/test/rustdoc/no_std-primitive.rs [new file with mode: 0644]
src/test/rustdoc/primitive/no_std.rs [new file with mode: 0644]
src/test/rustdoc/synthetic_auto/no-redundancy.rs
src/test/rustdoc/table-in-docblock.rs [new file with mode: 0644]
src/test/ui/anon-params/anon-params-denied-2018.stderr
src/test/ui/array-slice-vec/slice_binary_search.rs
src/test/ui/asm/parse-error.rs
src/test/ui/asm/parse-error.stderr
src/test/ui/associated-consts/associated-const-in-trait.stderr
src/test/ui/associated-item/issue-48027.stderr
src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
src/test/ui/associated-types/associated-types-bound-failure.stderr
src/test/ui/associated-types/associated-types-path-1.stderr
src/test/ui/associated-types/associated-types-path-2.rs
src/test/ui/associated-types/associated-types-path-2.stderr
src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
src/test/ui/associated-types/issue-19883.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-19883.stderr [new file with mode: 0644]
src/test/ui/associated-types/issue-21363.rs [new file with mode: 0644]
src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
src/test/ui/async-await/auxiliary/issue-72470-lib.rs [new file with mode: 0644]
src/test/ui/async-await/issue-72442.stderr
src/test/ui/async-await/issue-72470-llvm-dominate.rs [new file with mode: 0644]
src/test/ui/async-await/issue-76547.nll.stderr
src/test/ui/async-await/issues/issue-54752-async-block.stderr
src/test/ui/async-await/issues/issue-65159.rs
src/test/ui/async-await/issues/issue-65159.stderr
src/test/ui/auxiliary/define-macro.rs [deleted file]
src/test/ui/auxiliary/issue-72470-lib.rs [deleted file]
src/test/ui/borrowck/borrowck-in-static.stderr
src/test/ui/borrowck/borrowck-move-by-capture.stderr
src/test/ui/borrowck/borrowck-unused-mut-locals.rs
src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.rs
src/test/ui/borrowck/issue-82126-mismatched-subst-and-hir.stderr
src/test/ui/borrowck/issue-82462.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-82462.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-82462.stderr [new file with mode: 0644]
src/test/ui/borrowck/issue-87456-point-to-closure.rs [new file with mode: 0644]
src/test/ui/borrowck/issue-87456-point-to-closure.stderr [new file with mode: 0644]
src/test/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
src/test/ui/box/into-boxed-slice-fail.stderr
src/test/ui/bug-7183-generics.rs [deleted file]
src/test/ui/chalkify/type_inference.stderr
src/test/ui/closure-expected.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs
src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs
src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs
src/test/ui/closures/closure-bounds-subtype.stderr
src/test/ui/closures/coerce-unsafe-to-closure.stderr
src/test/ui/closures/issue-78720.rs [new file with mode: 0644]
src/test/ui/closures/issue-78720.stderr [new file with mode: 0644]
src/test/ui/coercion/issue-88097.rs [new file with mode: 0644]
src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
src/test/ui/coherence/coherence-projection-conflict-orphan.stderr
src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
src/test/ui/const-generics/broken-mir-2.rs
src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
src/test/ui/const-generics/generic_const_exprs/closures.stderr
src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr [new file with mode: 0644]
src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
src/test/ui/const-generics/issues/issue-67375.full.stderr
src/test/ui/const-generics/issues/issue-67945-2.full.stderr
src/test/ui/const-generics/issues/issue-86530.stderr
src/test/ui/const-generics/issues/issue-87493.rs [new file with mode: 0644]
src/test/ui/const-generics/issues/issue-87493.stderr [new file with mode: 0644]
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/unused_braces.stderr
src/test/ui/consts/const-eval/const_panic.rs
src/test/ui/consts/const-eval/const_panic.stderr
src/test/ui/consts/const-eval/const_panic_2021.rs
src/test/ui/consts/const-eval/const_panic_2021.stderr
src/test/ui/consts/const_fn_trait_bound.rs
src/test/ui/consts/const_fn_trait_bound.stock.stderr
src/test/ui/consts/issue-23833.rs [new file with mode: 0644]
src/test/ui/consts/issue-34784.rs [new file with mode: 0644]
src/test/ui/consts/issue-89088.rs [new file with mode: 0644]
src/test/ui/consts/min_const_fn/min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn.stderr
src/test/ui/consts/min_const_fn/min_const_fn_dyn.rs
src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
src/test/ui/consts/refs_check_const_eq-issue-88384.rs [new file with mode: 0644]
src/test/ui/consts/refs_check_const_eq-issue-88384.stderr [new file with mode: 0644]
src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs [new file with mode: 0644]
src/test/ui/derives/clone-debug-dead-code.rs [new file with mode: 0644]
src/test/ui/derives/clone-debug-dead-code.stderr [new file with mode: 0644]
src/test/ui/derives/deriving-copyclone.stderr
src/test/ui/deriving/deriving-clone-generic-struct.rs
src/test/ui/deriving/deriving-clone-struct.rs
src/test/ui/deriving/deriving-clone-tuple-struct.rs
src/test/ui/deriving/deriving-in-fn.rs
src/test/ui/deriving/issue-3935.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr [new file with mode: 0644]
src/test/ui/discrim/discrim-ill-typed.stderr
src/test/ui/enable-unstable-lib-feature.rs [deleted file]
src/test/ui/enable-unstable-lib-feature.stderr [deleted file]
src/test/ui/enum-discriminant/niche-prefer-zero.rs [new file with mode: 0644]
src/test/ui/error-codes/E0038.stderr
src/test/ui/error-codes/E0221.stderr
src/test/ui/error-codes/E0277.stderr
src/test/ui/error-codes/E0439.rs [deleted file]
src/test/ui/error-codes/E0439.stderr [deleted file]
src/test/ui/error-should-say-copy-not-pod.stderr
src/test/ui/expr-empty-ret.rs [deleted file]
src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed [new file with mode: 0644]
src/test/ui/expr/malformed_closure/missing_braces_around_block.rs [new file with mode: 0644]
src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr [new file with mode: 0644]
src/test/ui/expr/malformed_closure/ruby_style_closure.rs [new file with mode: 0644]
src/test/ui/expr/malformed_closure/ruby_style_closure.stderr [new file with mode: 0644]
src/test/ui/extern/extern-wrong-value-type.stderr
src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
src/test/ui/feature-gates/feature-gate-unnamed_fields.rs [deleted file]
src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr [deleted file]
src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
src/test/ui/float-literal-inference-restrictions.stderr
src/test/ui/fn/fn-trait-formatting.stderr
src/test/ui/generator/issue-88653.rs [new file with mode: 0644]
src/test/ui/generator/issue-88653.stderr [new file with mode: 0644]
src/test/ui/generator/static-not-unpin.stderr
src/test/ui/generic-associated-types/gat-in-trait-path.stderr
src/test/ui/generic-associated-types/impl_bounds.rs
src/test/ui/generic-associated-types/impl_bounds.stderr
src/test/ui/generic-associated-types/issue-67510-pass.stderr
src/test/ui/generic-associated-types/issue-76535.stderr
src/test/ui/generic-associated-types/issue-78671.stderr
src/test/ui/generic-associated-types/issue-79422.stderr
src/test/ui/generic-associated-types/issue-86787.stderr
src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs [new file with mode: 0644]
src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr [new file with mode: 0644]
src/test/ui/generic-associated-types/trait-objects.stderr
src/test/ui/generics/mid-path-type-params.rs [new file with mode: 0644]
src/test/ui/guards.rs [deleted file]
src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
src/test/ui/hrtb/issue-88446.rs [new file with mode: 0644]
src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs [new file with mode: 0644]
src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr [new file with mode: 0644]
src/test/ui/indexing-requires-a-uint.stderr
src/test/ui/inference/issue-71309.rs [new file with mode: 0644]
src/test/ui/inference/issue-71309.stderr [new file with mode: 0644]
src/test/ui/integer-literal-suffix-inference.stderr
src/test/ui/issue-72470-llvm-dominate.rs [deleted file]
src/test/ui/issues/issue-13359.stderr
src/test/ui/issues/issue-1362.stderr
src/test/ui/issues/issue-1448-2.stderr
src/test/ui/issues/issue-17651.rs
src/test/ui/issues/issue-17651.stderr
src/test/ui/issues/issue-18959.stderr
src/test/ui/issues/issue-19358.rs
src/test/ui/issues/issue-19538.stderr
src/test/ui/issues/issue-19883.rs [deleted file]
src/test/ui/issues/issue-19883.stderr [deleted file]
src/test/ui/issues/issue-20605.stderr
src/test/ui/issues/issue-20692.rs [deleted file]
src/test/ui/issues/issue-20692.stderr [deleted file]
src/test/ui/issues/issue-21363.rs [deleted file]
src/test/ui/issues/issue-23825.rs [deleted file]
src/test/ui/issues/issue-23833.rs [deleted file]
src/test/ui/issues/issue-23966.stderr
src/test/ui/issues/issue-25076.stderr
src/test/ui/issues/issue-28098.stderr
src/test/ui/issues/issue-30355.stderr
src/test/ui/issues/issue-33498.rs [deleted file]
src/test/ui/issues/issue-34194.rs [deleted file]
src/test/ui/issues/issue-34255-1.rs
src/test/ui/issues/issue-34255-1.stderr
src/test/ui/issues/issue-34784.rs [deleted file]
src/test/ui/issues/issue-35376.rs [deleted file]
src/test/ui/issues/issue-35376.stderr [deleted file]
src/test/ui/issues/issue-36768.rs [deleted file]
src/test/ui/issues/issue-37433.rs [deleted file]
src/test/ui/issues/issue-37433.stderr [deleted file]
src/test/ui/issues/issue-3794.rs
src/test/ui/issues/issue-38002.rs [deleted file]
src/test/ui/issues/issue-3935.rs [deleted file]
src/test/ui/issues/issue-41255.rs [deleted file]
src/test/ui/issues/issue-41255.stderr [deleted file]
src/test/ui/issues/issue-42944.rs [deleted file]
src/test/ui/issues/issue-42944.stderr [deleted file]
src/test/ui/issues/issue-4335.stderr
src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr [deleted file]
src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs [deleted file]
src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr [deleted file]
src/test/ui/issues/issue-47706-trait.stderr
src/test/ui/issues/issue-47706.stderr
src/test/ui/issues/issue-51102.stderr
src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
src/test/ui/issues/issue-53912.rs [deleted file]
src/test/ui/issues/issue-55796.stderr
src/test/ui/issues/issue-56031.stderr
src/test/ui/issues/issue-56685.rs [deleted file]
src/test/ui/issues/issue-56685.stderr [deleted file]
src/test/ui/issues/issue-57410.rs [deleted file]
src/test/ui/issues/issue-5791.rs [deleted file]
src/test/ui/issues/issue-5791.stderr [deleted file]
src/test/ui/issues/issue-59494.stderr
src/test/ui/issues/issue-60218.stderr
src/test/ui/issues/issue-60283.stderr
src/test/ui/issues/issue-61882-2.stderr
src/test/ui/issues/issue-66353.stderr
src/test/ui/issues/issue-74614.rs [deleted file]
src/test/ui/issues/issue-75777.stderr
src/test/ui/issues/issue-78720.rs [deleted file]
src/test/ui/issues/issue-78720.stderr [deleted file]
src/test/ui/issues/issue-79593.rs [deleted file]
src/test/ui/issues/issue-79593.stderr [deleted file]
src/test/ui/issues/issue-79744.rs [deleted file]
src/test/ui/issues/issue-79744.stderr [deleted file]
src/test/ui/issues/issue-86865.rs [new file with mode: 0644]
src/test/ui/issues/issue-86865.stderr [new file with mode: 0644]
src/test/ui/issues/issue-87199.stderr
src/test/ui/issues/issue-8761.stderr
src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs [deleted file]
src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr [deleted file]
src/test/ui/kindck/kindck-impl-type-params-2.stderr
src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
src/test/ui/lifetimes/issue-77175.rs [new file with mode: 0644]
src/test/ui/lifetimes/undeclared-lifetime-used-in-debug-macro-issue-70152.stderr
src/test/ui/lint/enable-unstable-lib-feature.rs [new file with mode: 0644]
src/test/ui/lint/enable-unstable-lib-feature.stderr [new file with mode: 0644]
src/test/ui/lint/issue-57410.rs [new file with mode: 0644]
src/test/ui/lint/issue-79744.rs [new file with mode: 0644]
src/test/ui/lint/issue-79744.stderr [new file with mode: 0644]
src/test/ui/lint/lint-unnecessary-parens.stderr
src/test/ui/lint/suggestions.stderr
src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
src/test/ui/lint/unused_braces.stderr
src/test/ui/lint/unused_braces_borrow.stderr
src/test/ui/lint/unused_parens_json_suggestion.stderr
src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
src/test/ui/llvm-asm/issue-37433.rs [new file with mode: 0644]
src/test/ui/llvm-asm/issue-37433.stderr [new file with mode: 0644]
src/test/ui/loops/loops-reject-duplicate-labels-2.rs
src/test/ui/loops/loops-reject-duplicate-labels-2.stderr
src/test/ui/loops/loops-reject-duplicate-labels.rs
src/test/ui/loops/loops-reject-duplicate-labels.stderr
src/test/ui/loops/loops-reject-lifetime-shadowing-label.rs
src/test/ui/loops/loops-reject-lifetime-shadowing-label.stderr
src/test/ui/macros/auxiliary/define-macro.rs [new file with mode: 0644]
src/test/ui/macros/lint-trailing-macro-call.rs [new file with mode: 0644]
src/test/ui/macros/lint-trailing-macro-call.stderr [new file with mode: 0644]
src/test/ui/macros/out-of-order-shadowing.rs [new file with mode: 0644]
src/test/ui/macros/out-of-order-shadowing.stderr [new file with mode: 0644]
src/test/ui/match/guards.rs [new file with mode: 0644]
src/test/ui/match/issue-33498.rs [new file with mode: 0644]
src/test/ui/match/issue-41255.rs [new file with mode: 0644]
src/test/ui/match/issue-41255.stderr [new file with mode: 0644]
src/test/ui/match/issue-56685.rs [new file with mode: 0644]
src/test/ui/match/issue-56685.stderr [new file with mode: 0644]
src/test/ui/meta/expected-error-correct-rev.a.stderr
src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr
src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
src/test/ui/mid-path-type-params.rs [deleted file]
src/test/ui/mir/remove-zsts-query-cycle.rs [new file with mode: 0644]
src/test/ui/mismatched_types/E0631.stderr
src/test/ui/mismatched_types/closure-arg-count.stderr
src/test/ui/mismatched_types/fn-variance-1.stderr
src/test/ui/mismatched_types/issue-26480.stderr
src/test/ui/mismatched_types/numeric-literal-cast.stderr
src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
src/test/ui/monomorphize-abi-alignment.rs
src/test/ui/moves/move-1-unique.rs
src/test/ui/moves/move-3-unique.rs
src/test/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
src/test/ui/mutexguard-sync.stderr
src/test/ui/namespace/namespace-mix.stderr
src/test/ui/never_type/expr-empty-ret.rs [new file with mode: 0644]
src/test/ui/nll/issue-46036.stderr
src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
src/test/ui/nll/issue-55394.stderr
src/test/ui/nll/type-alias-free-regions.stderr
src/test/ui/nll/user-annotations/adt-brace-enums.stderr
src/test/ui/nll/user-annotations/adt-brace-structs.stderr
src/test/ui/nll/user-annotations/adt-tuple-enums.stderr
src/test/ui/nll/user-annotations/adt-tuple-struct.stderr
src/test/ui/nll/where_clauses_in_structs.stderr
src/test/ui/no_send-rc.stderr
src/test/ui/no_send-struct.stderr
src/test/ui/no_share-struct.stderr
src/test/ui/numeric/const-scope.stderr
src/test/ui/numeric/len.stderr
src/test/ui/numeric/numeric-cast-2.stderr
src/test/ui/numeric/numeric-cast-binop.stderr
src/test/ui/numeric/numeric-cast-no-fix.stderr
src/test/ui/numeric/numeric-cast.stderr
src/test/ui/numeric/numeric-fields.stderr
src/test/ui/numeric/numeric-suffix.stderr
src/test/ui/object-does-not-impl-trait.stderr
src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
src/test/ui/object-safety/object-safety-generics.curr.stderr
src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
src/test/ui/on-unimplemented/enclosing-scope.stderr
src/test/ui/on-unimplemented/multiple-impls.stderr
src/test/ui/on-unimplemented/on-impl.stderr
src/test/ui/out-of-order-shadowing.rs [deleted file]
src/test/ui/out-of-order-shadowing.stderr [deleted file]
src/test/ui/overloaded/overloaded-autoderef-order.rs
src/test/ui/parser/expr-as-stmt.fixed
src/test/ui/parser/expr-as-stmt.rs
src/test/ui/parser/expr-as-stmt.stderr
src/test/ui/parser/inverted-parameters.stderr
src/test/ui/parser/issue-44406.rs
src/test/ui/parser/issue-44406.stderr
src/test/ui/parser/issue-88583-union-as-ident.rs [new file with mode: 0644]
src/test/ui/parser/issue-88818.rs [new file with mode: 0644]
src/test/ui/parser/issue-88818.stderr [new file with mode: 0644]
src/test/ui/parser/lifetime-in-pattern.stderr
src/test/ui/parser/macro-braces-dot-question.rs [new file with mode: 0644]
src/test/ui/parser/omitted-arg-in-item-fn.stderr
src/test/ui/parser/pat-lt-bracket-2.stderr
src/test/ui/parser/recover-for-loop-parens-around-head.rs
src/test/ui/parser/recover-for-loop-parens-around-head.stderr
src/test/ui/parser/recover-from-bad-variant.rs
src/test/ui/parser/recover-from-bad-variant.stderr
src/test/ui/parser/unicode-character-literal.fixed [new file with mode: 0644]
src/test/ui/parser/unicode-character-literal.rs [new file with mode: 0644]
src/test/ui/parser/unicode-character-literal.stderr [new file with mode: 0644]
src/test/ui/path-lookahead.stderr
src/test/ui/phantom-auto-trait.stderr
src/test/ui/polymorphization/issue-74614.rs [new file with mode: 0644]
src/test/ui/pptypedef.stderr
src/test/ui/privacy/issue-79593.rs [new file with mode: 0644]
src/test/ui/privacy/issue-79593.stderr [new file with mode: 0644]
src/test/ui/proc-macro/span-preservation.stderr
src/test/ui/regions/region-object-lifetime-in-coercion.stderr
src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
src/test/ui/regions/regions-creating-enums4.stderr
src/test/ui/regions/regions-ret-borrowed-1.stderr
src/test/ui/regions/regions-ret-borrowed.stderr
src/test/ui/regions/regions-trait-object-subtyping.stderr
src/test/ui/repeat_count.stderr
src/test/ui/repr/repr-transparent-issue-87496.rs [new file with mode: 0644]
src/test/ui/repr/repr-transparent-issue-87496.stderr [new file with mode: 0644]
src/test/ui/resolve/issue-42944.rs [new file with mode: 0644]
src/test/ui/resolve/issue-42944.stderr [new file with mode: 0644]
src/test/ui/resolve/use-self-in-inner-fn.rs [new file with mode: 0644]
src/test/ui/resolve/use-self-in-inner-fn.stderr [new file with mode: 0644]
src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs [new file with mode: 0644]
src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr [new file with mode: 0644]
src/test/ui/rfc-2008-non-exhaustive/struct.stderr
src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
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-nonconst.stderr
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/const-drop.rs [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs [new file with mode: 0644]
src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
src/test/ui/self/ufcs-explicit-self.rs
src/test/ui/shift-various-bad-types.stderr
src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs [new file with mode: 0644]
src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr [new file with mode: 0644]
src/test/ui/simd/monomorphize-shuffle-index.rs [new file with mode: 0644]
src/test/ui/simd/shuffle-not-out-of-bounds.rs
src/test/ui/simd/shuffle-not-out-of-bounds.stderr
src/test/ui/simd/shuffle.rs [new file with mode: 0644]
src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
src/test/ui/span/issue-34264.stderr
src/test/ui/specialization/issue-35376.rs [new file with mode: 0644]
src/test/ui/specialization/issue-35376.stderr [new file with mode: 0644]
src/test/ui/static/issue-34194.rs [new file with mode: 0644]
src/test/ui/str/str-idx.stderr
src/test/ui/str/str-mut-idx.stderr
src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs
src/test/ui/structs-enums/class-implement-traits.rs
src/test/ui/structs-enums/functional-struct-upd.rs
src/test/ui/structs-enums/issue-38002.rs [new file with mode: 0644]
src/test/ui/structs-enums/tag-align-shape.rs
src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr
src/test/ui/suggestions/issue-62843.stderr
src/test/ui/suggestions/issue-64252-self-type.stderr
src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
src/test/ui/suggestions/issue-84973-2.stderr
src/test/ui/suggestions/issue-84973-blacklist.rs
src/test/ui/suggestions/issue-84973-blacklist.stderr
src/test/ui/suggestions/issue-84973-negative.stderr
src/test/ui/suggestions/issue-84973.stderr
src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
src/test/ui/suggestions/option-content-move2.stderr
src/test/ui/suggestions/restrict-type-argument.stderr
src/test/ui/suggestions/slice-issue-87994.rs [new file with mode: 0644]
src/test/ui/suggestions/slice-issue-87994.stderr [new file with mode: 0644]
src/test/ui/suggestions/suggest-change-mut.stderr
src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
src/test/ui/symbol-names/issue-53912.rs [new file with mode: 0644]
src/test/ui/tail-typeck.stderr
src/test/ui/test-attrs/issue-36768.rs [new file with mode: 0644]
src/test/ui/thread-local/tls.rs [new file with mode: 0644]
src/test/ui/tls.rs [deleted file]
src/test/ui/traits/bound/same-crate-name.stderr
src/test/ui/traits/bug-7183-generics.rs [new file with mode: 0644]
src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
src/test/ui/traits/issue-20692.rs [new file with mode: 0644]
src/test/ui/traits/issue-20692.stderr [new file with mode: 0644]
src/test/ui/traits/issue-23825.rs [new file with mode: 0644]
src/test/ui/traits/item-privacy.stderr
src/test/ui/traits/multidispatch-bad.stderr
src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
src/test/ui/traits/reservation-impl/no-use.stderr
src/test/ui/traits/suggest-deferences/issue-39029.stderr
src/test/ui/traits/suggest-deferences/issue-62530.stderr
src/test/ui/traits/suggest-deferences/multiple-0.stderr
src/test/ui/traits/suggest-deferences/multiple-1.stderr
src/test/ui/traits/test-2.stderr
src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
src/test/ui/try-block/try-block-unused-delims.stderr
src/test/ui/tutorial-suffix-inference-test.stderr
src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs [new file with mode: 0644]
src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr [new file with mode: 0644]
src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
src/test/ui/typeck/issue-88803-call-expr-method.fixed [new file with mode: 0644]
src/test/ui/typeck/issue-88803-call-expr-method.rs [new file with mode: 0644]
src/test/ui/typeck/issue-88803-call-expr-method.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-88844.rs [new file with mode: 0644]
src/test/ui/typeck/issue-88844.stderr [new file with mode: 0644]
src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed [new file with mode: 0644]
src/test/ui/typeck/issue-89044-wrapped-expr-method.rs [new file with mode: 0644]
src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr [new file with mode: 0644]
src/test/ui/typeck/typeck-unsafe-always-share.stderr
src/test/ui/typeof/type_mismatch.stderr
src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
src/test/ui/unnamed_fields/restrict_anonymous.rs [deleted file]
src/test/ui/unnamed_fields/restrict_anonymous.stderr [deleted file]
src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr [new file with mode: 0644]
src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs [new file with mode: 0644]
src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr [new file with mode: 0644]
src/test/ui/unsized-locals/unsized-exprs.stderr
src/test/ui/unsized/unsized3.rs
src/test/ui/unsized/unsized3.stderr
src/test/ui/use-self-in-inner-fn.rs [deleted file]
src/test/ui/use-self-in-inner-fn.stderr [deleted file]
src/test/ui/vtable-res-trait-param.stderr
src/test/ui/wf/issue-87495.stderr
src/test/ui/wf/wf-object-safe.stderr
src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
src/test/ui/wrong-ret-type.stderr
src/tools/build-manifest/Cargo.toml
src/tools/build-manifest/src/main.rs
src/tools/bump-stage0/Cargo.toml
src/tools/cargo
src/tools/cargotest/Cargo.toml
src/tools/clippy/Cargo.toml
src/tools/clippy/clippy_dev/Cargo.toml
src/tools/clippy/clippy_dummy/Cargo.toml
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/attrs.rs
src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
src/tools/clippy/clippy_lints/src/copies.rs
src/tools/clippy/clippy_lints/src/doc.rs
src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
src/tools/clippy/clippy_lints/src/implicit_hasher.rs
src/tools/clippy/clippy_lints/src/large_const_arrays.rs
src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
src/tools/clippy/clippy_lints/src/loops/mod.rs
src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
src/tools/clippy/clippy_lints/src/macro_use.rs
src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs
src/tools/clippy/clippy_lints/src/module_style.rs
src/tools/clippy/clippy_lints/src/regex.rs
src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
src/tools/clippy/clippy_utils/Cargo.toml
src/tools/clippy/clippy_utils/src/higher.rs
src/tools/clippy/clippy_utils/src/lib.rs
src/tools/clippy/clippy_utils/src/paths.rs
src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
src/tools/clippy/lintcheck/Cargo.toml
src/tools/clippy/tests/ui/default_trait_access.fixed
src/tools/clippy/tests/ui/default_trait_access.rs
src/tools/compiletest/Cargo.toml
src/tools/compiletest/src/util.rs
src/tools/error_index_generator/Cargo.toml
src/tools/expand-yaml-anchors/Cargo.toml
src/tools/html-checker/Cargo.toml
src/tools/jsondocck/Cargo.toml
src/tools/linkchecker/Cargo.toml
src/tools/linkchecker/main.rs
src/tools/lint-docs/Cargo.toml
src/tools/lint-docs/src/lib.rs
src/tools/miri
src/tools/publish_toolstate.py
src/tools/remote-test-client/Cargo.toml
src/tools/remote-test-server/Cargo.toml
src/tools/rust-analyzer
src/tools/rust-demangler/Cargo.toml
src/tools/rustbook/Cargo.toml
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/rustdoc-themes/Cargo.toml
src/tools/rustdoc/Cargo.toml
src/tools/rustfmt/Cargo.toml
src/tools/rustfmt/src/items.rs
src/tools/rustfmt/src/lib.rs
src/tools/rustfmt/src/macros.rs
src/tools/rustfmt/src/modules.rs
src/tools/rustfmt/src/types.rs
src/tools/rustfmt/src/utils.rs
src/tools/tidy/Cargo.toml
src/tools/tidy/src/deps.rs
src/tools/tidy/src/edition.rs
src/tools/tidy/src/lib.rs
src/tools/tidy/src/main.rs
src/tools/tidy/src/primitive_docs.rs [new file with mode: 0644]
src/tools/tidy/src/ui_tests.rs
src/tools/tier-check/Cargo.toml
src/tools/unicode-table-generator/Cargo.toml
src/tools/unstable-book-gen/Cargo.toml
src/tools/x/Cargo.toml

index ff4fa1527e93ad09beb3f137c458c5c79bc18600..78ff874e7550114f3919a77a108a9fd93514b788 100644 (file)
@@ -404,6 +404,7 @@ jobs:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
               SCRIPT: python x.py dist
               DIST_REQUIRE_ALL_TOOLS: 0
+              WINDOWS_SDK_20348_HACK: 1
             os: windows-latest-xl
           - name: dist-i686-mingw
             env:
index 80acf227698e96f463c72f10dce219247dbe3767..5917757ff3e2198635a549d4a2c0113b9cd18472 100644 (file)
@@ -26,9 +26,9 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.13"
+version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
 dependencies = [
  "memchr",
 ]
@@ -267,7 +267,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
 
 [[package]]
 name = "cargo"
-version = "0.57.0"
+version = "0.58.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -559,7 +559,7 @@ dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_lints",
  "clippy_utils",
- "compiletest_rs 0.6.0",
+ "compiletest_rs",
  "derive-new",
  "filetime",
  "if_chain",
@@ -581,7 +581,7 @@ version = "0.0.1"
 dependencies = [
  "bytecount",
  "clap",
- "itertools 0.9.0",
+ "itertools 0.10.1",
  "opener",
  "regex",
  "shell-escape",
@@ -595,7 +595,7 @@ dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_utils",
  "if_chain",
- "itertools 0.9.0",
+ "itertools 0.10.1",
  "pulldown-cmark 0.8.0",
  "quine-mc_cluskey",
  "regex-syntax",
@@ -687,29 +687,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "compiletest_rs"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb"
-dependencies = [
- "diff",
- "filetime",
- "getopts",
- "lazy_static",
- "libc",
- "log",
- "miow",
- "regex",
- "rustfix 0.5.1",
- "serde",
- "serde_derive",
- "serde_json",
- "tempfile",
- "tester",
- "winapi",
-]
-
 [[package]]
 name = "compiletest_rs"
 version = "0.7.0"
@@ -2272,7 +2249,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "colored",
- "compiletest_rs 0.7.0",
+ "compiletest_rs",
  "env_logger 0.8.1",
  "getrandom 0.2.0",
  "hex 0.4.2",
@@ -2344,6 +2321,15 @@ dependencies = [
  "rustc-std-workspace-core",
 ]
 
+[[package]]
+name = "odht"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2504d29fda40b3f2f9ef525392435ab660e407c188196cb664b116ebcca0142"
+dependencies = [
+ "cfg-if 1.0.0",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.7.2"
@@ -3005,9 +2991,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.4.6"
+version = "1.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -3677,6 +3663,7 @@ dependencies = [
  "libc",
  "measureme",
  "rustc-demangle",
+ "rustc_arena",
  "rustc_ast",
  "rustc_attr",
  "rustc_codegen_ssa",
@@ -3881,6 +3868,7 @@ version = "0.0.0"
 name = "rustc_hir"
 version = "0.0.0"
 dependencies = [
+ "odht",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_feature",
@@ -4067,6 +4055,7 @@ name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
  "libc",
+ "odht",
  "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
index 37f90bf3c10088114deeac862538937f5ce3e881..277cf0f51d378afa6df85ec3fcbdf4f3a1f16a37 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc-main"
 version = "0.0.0"
-edition = '2018'
+edition = "2021"
 
 [dependencies]
 rustc_driver = { path = "../rustc_driver" }
index 9f266b1fb978d04b05f1e99f3c5fe7f55b300e7e..bb01d4f51b899d8e1329668951d53f59fa87ea9a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_apfloat"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 bitflags = "1.2.1"
index eba8a2a082f3ea4a72d7e62a8fedec1f470e7ade..33ccd0445030f7e0f315a2cee1b409a65ef9f142 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_arena"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 rustc_data_structures = { path = "../rustc_data_structures" }
index 67cf5d92b00cb7052e1d05f9b0840d0bca54a631..58b967a370415741c3f0ba94c5cd1af099070006 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_ast"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index b92c5fa072786331b9c57d2eff79243c43fb67c2..c27ab810a4c608f0e1cefc98c4881577b269f887 100644 (file)
@@ -1902,10 +1902,6 @@ pub enum TyKind {
     Never,
     /// A tuple (`(A, B, C, D,...)`).
     Tup(Vec<P<Ty>>),
-    /// An anonymous struct type i.e. `struct { foo: Type }`
-    AnonymousStruct(Vec<FieldDef>, bool),
-    /// An anonymous union type i.e. `union { bar: Type }`
-    AnonymousUnion(Vec<FieldDef>, bool),
     /// A path (`module::module::...::Type`), optionally
     /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
     ///
index 81195f7fb5cb2995ee4513aeac4cf0797158bcc1..5f17008bdc2b0747e118971443f2ca616f59d64c 100644 (file)
@@ -367,7 +367,7 @@ fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
             let is_first = i == 0;
             if !is_first {
                 let mod_sep_span =
-                    Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
+                    Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
                 idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
             }
             idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
index 2ec941cbb2466a95af61f5cb82254c7a1a0f4324..ba86036577ac5c1f5efb12102a19b13d783159f5 100644 (file)
@@ -484,9 +484,6 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
         TyKind::MacCall(mac) => vis.visit_mac_call(mac),
-        TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => {
-            fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
-        }
     }
     vis.visit_span(span);
     visit_lazy_tts(tokens, vis);
index c30f711b3970793fdde4b52ec1c3adc40740aefa..b38031042e0f09ed1265acf60725eca661dc84f5 100644 (file)
@@ -407,9 +407,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
         TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-        TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
-            walk_list!(visitor, visit_field_def, fields)
-        }
         TyKind::Never | TyKind::CVarArgs => {}
     }
 }
index 4e848a6a2b8fb2ffc4f003b88795dc1c915d2766..f4859ee4ae91f48133fe8684de01436d86dcb416 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_ast_lowering"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index ca804ec6758b727b23ae4b02d59159c7dbc2b556..14a894d61f4f5fdeeb5c8917b61a75b32025ba24 100644 (file)
@@ -55,7 +55,7 @@ fn lower_stmts(
                     }
                 }
                 StmtKind::Item(ref it) => {
-                    stmts.extend(self.lower_item_id(it).into_iter().enumerate().map(
+                    stmts.extend(self.lower_item_ref(it).into_iter().enumerate().map(
                         |(i, item_id)| {
                             let hir_id = match i {
                                 0 => self.lower_node_id(s.id),
index 16cd7a0bcdd394af214d0a0235fab976fb3c3636..a6ea4aa8923cfad252d7a96bdb11359f5c8256d3 100644 (file)
@@ -55,7 +55,6 @@ pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
                         0,
                         ParenthesizedGenericArgs::Err,
                         ImplTraitContext::disallowed(),
-                        None,
                     ));
                     let args = self.lower_exprs(args);
                     hir::ExprKind::MethodCall(
@@ -328,7 +327,7 @@ fn lower_legacy_const_generics(
         let mut generic_args = vec![];
         for (idx, arg) in args.into_iter().enumerate() {
             if legacy_args_idx.contains(&idx) {
-                let parent_def_id = self.current_hir_id_owner.0;
+                let parent_def_id = self.current_hir_id_owner;
                 let node_id = self.resolver.next_node_id();
 
                 // Add a definition for the in-band const def.
@@ -422,7 +421,9 @@ fn lower_expr_while_in_loop_scope(
         let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
         let if_expr = self.expr(span, if_kind, ThinVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
-        hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi()))
+        let span = self.lower_span(span.with_hi(cond.span.hi()));
+        let opt_label = self.lower_label(opt_label);
+        hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
     }
 
     /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
@@ -1450,8 +1451,13 @@ fn lower_expr_for(
             )
         };
 
+        // #82462: to correctly diagnose borrow errors, the block that contains
+        // the iter expr needs to have a span that covers the loop body.
+        let desugared_full_span =
+            self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e.span, None);
+
         let match_expr = self.arena.alloc(self.expr_match(
-            desugared_span,
+            desugared_full_span,
             into_iter_expr,
             arena_vec![self; iter_arm],
             hir::MatchSource::ForLoopDesugar,
@@ -1465,7 +1471,7 @@ fn lower_expr_for(
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps_mut(desugared_span, match_expr, attrs.into())
+        self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
index b7497c713f3df32d76a8f04ce0e6e98b0a4720c4..25e6fed68b566fcf5192cd88d81ea488d9a7fa5e 100644 (file)
@@ -41,21 +41,13 @@ fn with_trait_impl_ref<T>(
 impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     fn visit_item(&mut self, item: &'a Item) {
         let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
-            lctx.without_in_scope_lifetime_defs(|lctx| {
-                let hir_item = lctx.lower_item(item);
-                lctx.insert_item(hir_item)
-            })
+            let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item));
+            hir::OwnerNode::Item(node)
         });
 
         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));
                 }
@@ -78,24 +70,16 @@ fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
         self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
-            AssocCtxt::Trait => {
-                let hir_item = lctx.lower_trait_item(item);
-                lctx.insert_trait_item(hir_item);
-            }
-            AssocCtxt::Impl => {
-                let hir_item = lctx.lower_impl_item(item);
-                lctx.insert_impl_item(hir_item);
-            }
+            AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
+            AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
         });
 
         visit::walk_assoc_item(self, item, ctxt);
     }
 
     fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
-        self.lctx.allocate_hir_id_counter(item.id);
         self.lctx.with_hir_id_owner(item.id, |lctx| {
-            let hir_item = lctx.lower_foreign_item(item);
-            lctx.insert_foreign_item(hir_item);
+            hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
         });
 
         visit::walk_foreign_item(self, item);
@@ -110,12 +94,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
     // only used when lowering a child item of a trait or impl.
     fn with_parent_item_lifetime_defs<T>(
         &mut self,
-        parent_hir_id: hir::ItemId,
+        parent_hir_id: LocalDefId,
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
         let old_len = self.in_scope_lifetimes.len();
 
-        let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind {
+        let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind {
             hir::ItemKind::Impl(hir::Impl { ref generics, .. })
             | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
             _ => &[],
@@ -154,41 +138,28 @@ fn without_in_scope_lifetime_defs<T>(&mut self, f: impl FnOnce(&mut Self) -> T)
     pub(super) fn lower_mod(&mut self, items: &[P<Item>], inner: Span) -> hir::Mod<'hir> {
         hir::Mod {
             inner: self.lower_span(inner),
-            item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_id(x))),
+            item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))),
         }
     }
 
-    pub(super) fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
-        let node_ids = match i.kind {
-            ItemKind::Use(ref use_tree) => {
-                let mut vec = smallvec![i.id];
-                self.lower_item_id_use_tree(use_tree, i.id, &mut vec);
-                vec
-            }
-            ItemKind::Fn(..) | ItemKind::Impl(box ImplKind { of_trait: None, .. }) => {
-                smallvec![i.id]
-            }
-            _ => smallvec![i.id],
-        };
-
+    pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
+        let mut node_ids = smallvec![hir::ItemId { def_id: self.resolver.local_def_id(i.id) }];
+        if let ItemKind::Use(ref use_tree) = &i.kind {
+            self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
+        }
         node_ids
-            .into_iter()
-            .map(|node_id| hir::ItemId {
-                def_id: self.allocate_hir_id_counter(node_id).expect_owner(),
-            })
-            .collect()
     }
 
     fn lower_item_id_use_tree(
         &mut self,
         tree: &UseTree,
         base_id: NodeId,
-        vec: &mut SmallVec<[NodeId; 1]>,
+        vec: &mut SmallVec<[hir::ItemId; 1]>,
     ) {
         match tree.kind {
             UseTreeKind::Nested(ref nested_vec) => {
                 for &(ref nested, id) in nested_vec {
-                    vec.push(id);
+                    vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
                     self.lower_item_id_use_tree(nested, id, vec);
                 }
             }
@@ -197,25 +168,26 @@ fn lower_item_id_use_tree(
                 for (_, &id) in
                     iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
                 {
-                    vec.push(id);
+                    vec.push(hir::ItemId { def_id: self.resolver.local_def_id(id) });
                 }
             }
         }
     }
 
-    pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
+    fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
         let mut ident = i.ident;
-        let mut vis = self.lower_visibility(&i.vis, None);
+        let mut vis = self.lower_visibility(&i.vis);
         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);
-        hir::Item {
+        let item = hir::Item {
             def_id: hir_id.expect_owner(),
             ident: self.lower_ident(ident),
             kind,
             vis,
             span: self.lower_span(i.span),
-        }
+        };
+        self.arena.alloc(item)
     }
 
     fn lower_item_kind(
@@ -486,7 +458,7 @@ fn lower_use_tree(
                     }
                 }
 
-                let mut resolutions = self.expect_full_res_from_use(id);
+                let mut resolutions = self.expect_full_res_from_use(id).fuse();
                 // We want to return *something* from this function, so hold onto the first item
                 // for later.
                 let ret_res = self.lower_res(resolutions.next().unwrap_or(Res::Err));
@@ -496,7 +468,17 @@ fn lower_use_tree(
                 // won't be dealing with macros in the rest of the compiler.
                 // Essentially a single `use` which imports two names is desugared into
                 // two imports.
-                for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) {
+                for new_node_id in [id1, id2] {
+                    let new_id = self.resolver.local_def_id(new_node_id);
+                    let res = if let Some(res) = resolutions.next() {
+                        res
+                    } else {
+                        // Associate an HirId to both ids even if there is no resolution.
+                        self.node_id_to_hir_id.ensure_contains_elem(new_node_id, || None);
+                        debug_assert!(self.node_id_to_hir_id[new_node_id].is_none());
+                        self.node_id_to_hir_id[new_node_id] = Some(hir::HirId::make_owner(new_id));
+                        continue;
+                    };
                     let ident = *ident;
                     let mut path = path.clone();
                     for seg in &mut path.segments {
@@ -505,26 +487,26 @@ fn lower_use_tree(
                     let span = path.span;
 
                     self.with_hir_id_owner(new_node_id, |this| {
-                        let new_id = this.lower_node_id(new_node_id);
                         let res = this.lower_res(res);
-                        let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None);
+                        let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
                         let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
                         let vis = this.rebuild_vis(&vis);
                         if let Some(attrs) = attrs {
-                            this.attrs.insert(new_id, attrs);
+                            this.attrs.insert(hir::HirId::make_owner(new_id), attrs);
                         }
 
-                        this.insert_item(hir::Item {
-                            def_id: new_id.expect_owner(),
+                        let item = hir::Item {
+                            def_id: new_id,
                             ident: this.lower_ident(ident),
                             kind,
                             vis,
                             span: this.lower_span(span),
-                        });
+                        };
+                        hir::OwnerNode::Item(this.arena.alloc(item))
                     });
                 }
 
-                let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None);
+                let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
                 hir::ItemKind::Use(path, hir::UseKind::Single)
             }
             UseTreeKind::Glob => {
@@ -564,7 +546,7 @@ fn lower_use_tree(
 
                 // Add all the nested `PathListItem`s to the HIR.
                 for &(ref use_tree, id) in trees {
-                    let new_hir_id = self.lower_node_id(id);
+                    let new_hir_id = self.resolver.local_def_id(id);
 
                     let mut prefix = prefix.clone();
 
@@ -585,16 +567,17 @@ fn lower_use_tree(
                         let kind =
                             this.lower_use_tree(use_tree, &prefix, id, &mut vis, &mut ident, attrs);
                         if let Some(attrs) = attrs {
-                            this.attrs.insert(new_hir_id, attrs);
+                            this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs);
                         }
 
-                        this.insert_item(hir::Item {
-                            def_id: new_hir_id.expect_owner(),
+                        let item = hir::Item {
+                            def_id: new_hir_id,
                             ident: this.lower_ident(ident),
                             kind,
                             vis,
                             span: this.lower_span(use_tree.span),
-                        });
+                        };
+                        hir::OwnerNode::Item(this.arena.alloc(item))
                     });
                 }
 
@@ -624,7 +607,7 @@ fn lower_use_tree(
 
                 let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
                 let res = self.lower_res(res);
-                let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None);
+                let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
                 hir::ItemKind::Use(path, hir::UseKind::ListStem)
             }
         }
@@ -661,11 +644,11 @@ fn rebuild_vis(&mut self, vis: &hir::Visibility<'hir>) -> hir::Visibility<'hir>
         respan(self.lower_span(vis.span), vis_kind)
     }
 
-    fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
+    fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
         let hir_id = self.lower_node_id(i.id);
         let def_id = hir_id.expect_owner();
         self.lower_attrs(hir_id, &i.attrs);
-        hir::ForeignItem {
+        let item = hir::ForeignItem {
             def_id,
             ident: self.lower_ident(i.ident),
             kind: match i.kind {
@@ -693,17 +676,17 @@ fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
                 ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
                 ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
             },
-            vis: self.lower_visibility(&i.vis, None),
+            vis: self.lower_visibility(&i.vis),
             span: self.lower_span(i.span),
-        }
+        };
+        self.arena.alloc(item)
     }
 
-    fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
+    fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
         hir::ForeignItemRef {
-            id: hir::ForeignItemId { def_id: self.lower_node_id(i.id).expect_owner() },
+            id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) },
             ident: self.lower_ident(i.ident),
             span: self.lower_span(i.span),
-            vis: self.lower_visibility(&i.vis, Some(i.id)),
         }
     }
 
@@ -748,10 +731,7 @@ fn lower_variant_data(
         }
     }
 
-    pub(super) fn lower_field_def(
-        &mut self,
-        (index, f): (usize, &FieldDef),
-    ) -> hir::FieldDef<'hir> {
+    fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
         let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
             let t = self.lower_path_ty(
                 &f.ty,
@@ -774,12 +754,12 @@ pub(super) fn lower_field_def(
                 // FIXME(jseyfried): positional field hygiene.
                 None => Ident::new(sym::integer(index), self.lower_span(f.span)),
             },
-            vis: self.lower_visibility(&f.vis, None),
+            vis: self.lower_visibility(&f.vis),
             ty,
         }
     }
 
-    fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
+    fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
         let hir_id = self.lower_node_id(i.id);
         let trait_item_def_id = hir_id.expect_owner();
 
@@ -822,13 +802,14 @@ fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
         };
 
         self.lower_attrs(hir_id, &i.attrs);
-        hir::TraitItem {
+        let item = hir::TraitItem {
             def_id: trait_item_def_id,
             ident: self.lower_ident(i.ident),
             generics,
             kind,
             span: self.lower_span(i.span),
-        }
+        };
+        self.arena.alloc(item)
     }
 
     fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
@@ -842,7 +823,7 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
             }
             AssocItemKind::MacCall(..) => unimplemented!(),
         };
-        let id = hir::TraitItemId { def_id: self.lower_node_id(i.id).expect_owner() };
+        let id = hir::TraitItemId { def_id: self.resolver.local_def_id(i.id) };
         let defaultness = hir::Defaultness::Default { has_value: has_default };
         hir::TraitItemRef {
             id,
@@ -858,7 +839,7 @@ fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
         self.expr(span, hir::ExprKind::Err, AttrVec::new())
     }
 
-    fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
+    fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
         let impl_item_def_id = self.resolver.local_def_id(i.id);
 
         let (generics, kind) = match &i.kind {
@@ -912,26 +893,26 @@ fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
         let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
         let hir_id = self.lower_node_id(i.id);
         self.lower_attrs(hir_id, &i.attrs);
-        hir::ImplItem {
+        let item = hir::ImplItem {
             def_id: hir_id.expect_owner(),
             ident: self.lower_ident(i.ident),
             generics,
-            vis: self.lower_visibility(&i.vis, None),
+            vis: self.lower_visibility(&i.vis),
             defaultness,
             kind,
             span: self.lower_span(i.span),
-        }
+        };
+        self.arena.alloc(item)
     }
 
-    fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
+    fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
         // Since `default impl` is not yet implemented, this is always true in impls.
         let has_value = true;
         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() },
+            id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) },
             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 {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
@@ -949,25 +930,15 @@ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
     /// lowered. This can happen during `lower_impl_item_ref()` where we need to
     /// lower a `Visibility` value although we haven't lowered the owning
     /// `ImplItem` in question yet.
-    fn lower_visibility(
-        &mut self,
-        v: &Visibility,
-        explicit_owner: Option<NodeId>,
-    ) -> hir::Visibility<'hir> {
+    fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> {
         let node = match v.kind {
             VisibilityKind::Public => hir::VisibilityKind::Public,
             VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
             VisibilityKind::Restricted { ref path, id } => {
                 debug!("lower_visibility: restricted path id = {:?}", id);
-                let lowered_id = if let Some(owner) = explicit_owner {
-                    self.lower_node_id_with_owner(id, owner)
-                } else {
-                    self.lower_node_id(id)
-                };
-                let res = self.expect_full_res(id);
-                let res = self.lower_res(res);
+                let lowered_id = self.lower_node_id(id);
                 hir::VisibilityKind::Restricted {
-                    path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner),
+                    path: self.lower_path(id, path, ParamMode::Explicit),
                     hir_id: lowered_id,
                 }
             }
index fa14764c42a73f1707ac51729632769601f83de1..5ec060f654090b5297dbafac9ae91fe14617acf7 100644 (file)
@@ -38,7 +38,7 @@
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, TokenStream, TokenTree};
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit;
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
@@ -80,8 +80,6 @@ macro_rules! arena_vec {
 mod pat;
 mod path;
 
-const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
-
 rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
 
 struct LoweringContext<'a, 'hir: 'a> {
@@ -102,8 +100,6 @@ struct LoweringContext<'a, 'hir: 'a> {
     owners: IndexVec<LocalDefId, Option<hir::OwnerNode<'hir>>>,
     bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
 
-    modules: BTreeMap<LocalDefId, hir::ModuleItems>,
-
     generator_kind: Option<hir::GeneratorKind>,
 
     attrs: BTreeMap<hir::HirId, &'hir [Attribute]>,
@@ -152,10 +148,8 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// vector.
     in_scope_lifetimes: Vec<ParamName>,
 
-    current_module: LocalDefId,
-
-    current_hir_id_owner: (LocalDefId, u32),
-    item_local_id_counters: NodeMap<u32>,
+    current_hir_id_owner: LocalDefId,
+    item_local_id_counter: hir::ItemLocalId,
     node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
 
     allow_try_trait: Option<Lrc<[Symbol]>>,
@@ -165,6 +159,8 @@ struct LoweringContext<'a, 'hir: 'a> {
 pub trait ResolverAstLowering {
     fn def_key(&mut self, id: DefId) -> DefKey;
 
+    fn def_span(&self, id: LocalDefId) -> Span;
+
     fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
 
     fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
@@ -215,6 +211,11 @@ fn hash_spans(&self) -> bool {
         true
     }
 
+    #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
     #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
@@ -320,7 +321,6 @@ pub fn lower_crate<'a, 'hir>(
         arena,
         owners: IndexVec::default(),
         bodies: BTreeMap::new(),
-        modules: BTreeMap::new(),
         attrs: BTreeMap::default(),
         catch_scope: None,
         loop_scope: None,
@@ -328,9 +328,8 @@ pub fn lower_crate<'a, 'hir>(
         is_in_trait_impl: false,
         is_in_dyn_type: false,
         anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
-        current_module: CRATE_DEF_ID,
-        current_hir_id_owner: (CRATE_DEF_ID, 0),
-        item_local_id_counters: Default::default(),
+        current_hir_id_owner: CRATE_DEF_ID,
+        item_local_id_counter: hir::ItemLocalId::new(0),
         node_id_to_hir_id: IndexVec::new(),
         generator_kind: None,
         task_context: None,
@@ -411,66 +410,15 @@ enum AnonymousLifetimeMode {
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
-        /// Full-crate AST visitor that inserts into a fresh
-        /// `LoweringContext` any information that may be
-        /// needed from arbitrary locations in the crate,
-        /// e.g., the number of lifetime generic parameters
-        /// declared for every type and trait definition.
-        struct MiscCollector<'tcx, 'lowering, 'hir> {
-            lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
-        }
-
-        impl MiscCollector<'_, '_, '_> {
-            fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree) {
-                match tree.kind {
-                    UseTreeKind::Simple(_, id1, id2) => {
-                        for id in [id1, id2] {
-                            self.lctx.allocate_hir_id_counter(id);
-                        }
-                    }
-                    UseTreeKind::Glob => (),
-                    UseTreeKind::Nested(ref trees) => {
-                        for &(ref use_tree, id) in trees {
-                            self.lctx.allocate_hir_id_counter(id);
-                            self.allocate_use_tree_hir_id_counters(use_tree);
-                        }
-                    }
-                }
-            }
-        }
-
-        impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
-            fn visit_item(&mut self, item: &'tcx Item) {
-                self.lctx.allocate_hir_id_counter(item.id);
-
-                if let ItemKind::Use(ref use_tree) = item.kind {
-                    self.allocate_use_tree_hir_id_counters(use_tree);
-                }
-
-                visit::walk_item(self, item);
-            }
+        debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
 
-            fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
-                self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_assoc_item(self, item, ctxt);
-            }
-
-            fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
-                self.lctx.allocate_hir_id_counter(item.id);
-                visit::walk_foreign_item(self, item);
-            }
-        }
-
-        self.lower_node_id(CRATE_NODE_ID);
-        debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
-
-        visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
         visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
 
-        let module = self.arena.alloc(self.lower_mod(&c.items, c.span));
-        self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
-        self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
-        self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
+        self.with_hir_id_owner(CRATE_NODE_ID, |lctx| {
+            let module = lctx.lower_mod(&c.items, c.span);
+            lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
+            hir::OwnerNode::Crate(lctx.arena.alloc(module))
+        });
 
         let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
         for (k, v) in self.resolver.take_trait_map().into_iter() {
@@ -501,61 +449,11 @@ fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
             }
         }
 
-        let krate = hir::Crate {
-            owners: self.owners,
-            bodies: self.bodies,
-            modules: self.modules,
-            trait_map,
-            attrs: self.attrs,
-        };
+        let krate =
+            hir::Crate { owners: self.owners, bodies: self.bodies, trait_map, attrs: self.attrs };
         self.arena.alloc(krate)
     }
 
-    fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
-        let id = item.item_id();
-        let item = self.arena.alloc(item);
-        self.owners.ensure_contains_elem(id.def_id, || None);
-        self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
-        self.modules.entry(self.current_module).or_default().items.insert(id);
-        id
-    }
-
-    fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId {
-        let id = item.foreign_item_id();
-        let item = self.arena.alloc(item);
-        self.owners.ensure_contains_elem(id.def_id, || None);
-        self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
-        self.modules.entry(self.current_module).or_default().foreign_items.insert(id);
-        id
-    }
-
-    fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
-        let id = item.impl_item_id();
-        let item = self.arena.alloc(item);
-        self.owners.ensure_contains_elem(id.def_id, || None);
-        self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
-        self.modules.entry(self.current_module).or_default().impl_items.insert(id);
-        id
-    }
-
-    fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId {
-        let id = item.trait_item_id();
-        let item = self.arena.alloc(item);
-        self.owners.ensure_contains_elem(id.def_id, || None);
-        self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
-        self.modules.entry(self.current_module).or_default().trait_items.insert(id);
-        id
-    }
-
-    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);
-        // Always allocate the first `HirId` for the owner itself.
-        let lowered = self.lower_node_id_with_owner(owner, owner);
-        debug_assert_eq!(lowered.local_id.as_u32(), 0);
-        lowered
-    }
-
     fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
         LoweringHasher {
             source_map: CachingSourceMapView::new(self.sess.source_map()),
@@ -563,47 +461,33 @@ fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
         }
     }
 
-    fn lower_node_id_generic(
+    fn with_hir_id_owner(
         &mut self,
-        ast_node_id: NodeId,
-        alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
-    ) -> hir::HirId {
-        assert_ne!(ast_node_id, DUMMY_NODE_ID);
-
-        let min_size = ast_node_id.as_usize() + 1;
+        owner: NodeId,
+        f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
+    ) -> LocalDefId {
+        let def_id = self.resolver.local_def_id(owner);
 
-        if min_size > self.node_id_to_hir_id.len() {
-            self.node_id_to_hir_id.resize(min_size, None);
+        // Always allocate the first `HirId` for the owner itself.
+        self.node_id_to_hir_id.ensure_contains_elem(owner, || None);
+        if let Some(_lowered) = self.node_id_to_hir_id[owner] {
+            panic!("with_hir_id_owner must not be called multiple times on owner {:?}", def_id);
         }
+        self.node_id_to_hir_id[owner] = Some(hir::HirId::make_owner(def_id));
 
-        if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
-            existing_hir_id
-        } else {
-            // Generate a new `HirId`.
-            let hir_id = alloc_hir_id(self);
-            self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
+        let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
+        let current_local_counter =
+            std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
 
-            hir_id
-        }
-    }
+        let item = f(self);
 
-    fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
-        let counter = self
-            .item_local_id_counters
-            .insert(owner, HIR_ID_COUNTER_LOCKED)
-            .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
-        let def_id = self.resolver.local_def_id(owner);
-        let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter));
-        let ret = f(self);
-        let (new_def_id, new_counter) =
-            std::mem::replace(&mut self.current_hir_id_owner, old_owner);
+        self.current_hir_id_owner = current_owner;
+        self.item_local_id_counter = current_local_counter;
 
-        debug_assert!(def_id == new_def_id);
-        debug_assert!(new_counter >= counter);
+        self.owners.ensure_contains_elem(def_id, || None);
+        self.owners[def_id] = Some(item);
 
-        let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
-        debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
-        ret
+        def_id
     }
 
     /// This method allocates a new `HirId` for the given `NodeId` and stores it in
@@ -613,35 +497,20 @@ fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T
     /// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
     /// properly. Calling the method twice with the same `NodeId` is fine though.
     fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
-        self.lower_node_id_generic(ast_node_id, |this| {
-            let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner;
-            let local_id = *local_id_counter;
-            *local_id_counter += 1;
-            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
-        })
-    }
-
-    fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId {
-        self.lower_node_id_generic(ast_node_id, |this| {
-            let local_id_counter = this
-                .item_local_id_counters
-                .get_mut(&owner)
-                .expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`");
-            let local_id = *local_id_counter;
-
-            // We want to be sure not to modify the counter in the map while it
-            // is also on the stack. Otherwise we'll get lost updates when writing
-            // back from the stack to the map.
-            debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
-
-            *local_id_counter += 1;
-            let owner = this.resolver.opt_local_def_id(owner).expect(
-                "you forgot to call `create_def` or are lowering node-IDs \
-                 that do not belong to the current owner",
-            );
+        assert_ne!(ast_node_id, DUMMY_NODE_ID);
 
-            hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
-        })
+        self.node_id_to_hir_id.ensure_contains_elem(ast_node_id, || None);
+        if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
+            existing_hir_id
+        } else {
+            // Generate a new `HirId`.
+            let owner = self.current_hir_id_owner;
+            let local_id = self.item_local_id_counter;
+            self.item_local_id_counter.increment_by(1);
+            let hir_id = hir::HirId { owner, local_id };
+            self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
+            hir_id
+        }
     }
 
     fn next_id(&mut self) -> hir::HirId {
@@ -651,7 +520,7 @@ fn next_id(&mut self) -> hir::HirId {
 
     fn lower_res(&mut self, res: Res<NodeId>) -> Res {
         res.map_id(|id| {
-            self.lower_node_id_generic(id, |_| {
+            self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| {
                 panic!("expected `NodeId` to be lowered already for res {:#?}", res);
             })
         })
@@ -711,9 +580,14 @@ fn with_anonymous_lifetime_mode<R>(
     }
 
     /// Intercept all spans entering HIR.
-    /// For now we are not doing anything with the intercepted spans.
+    /// Mark a span as relative to the current owning item.
     fn lower_span(&self, span: Span) -> Span {
-        span
+        if self.sess.opts.debugging_opts.incremental_relative_spans {
+            span.with_parent(Some(self.current_hir_id_owner))
+        } else {
+            // Do not make spans relative when not using incremental compilation.
+            span
+        }
     }
 
     fn lower_ident(&self, ident: Ident) -> Ident {
@@ -781,7 +655,7 @@ fn lifetime_to_generic_param(
             node_id,
             DefPathData::LifetimeNs(str_name),
             ExpnId::root(),
-            span,
+            span.with_parent(None),
         );
 
         hir::GenericParam {
@@ -882,7 +756,7 @@ fn add_in_band_defs<T>(
                     // wouldn't have been added yet.
                     let generics = this.lower_generics_mut(
                         generics,
-                        ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0),
+                        ImplTraitContext::Universal(&mut params, this.current_hir_id_owner),
                     );
                     let res = f(this, &mut params);
                     (params, (generics, res))
@@ -1088,7 +962,7 @@ fn lower_assoc_ty_constraint(
             }
             AssocTyConstraintKind::Bound { ref bounds } => {
                 let mut capturable_lifetimes;
-                let mut parent_def_id = self.current_hir_id_owner.0;
+                let mut parent_def_id = self.current_hir_id_owner;
                 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
                 let (desugar_to_impl_trait, itctx) = match itctx {
                     // We are in the return position:
@@ -1216,7 +1090,7 @@ fn lower_generic_arg(
 
                                 // Construct an AnonConst where the expr is the "ty"'s path.
 
-                                let parent_def_id = self.current_hir_id_owner.0;
+                                let parent_def_id = self.current_hir_id_owner;
                                 let node_id = self.resolver.next_node_id();
 
                                 // Add a definition for the in-band const def.
@@ -1289,15 +1163,6 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) ->
         let kind = match t.kind {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
-            // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
-            TyKind::AnonymousStruct(ref _fields, _recovered) => {
-                self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit();
-                hir::TyKind::Err
-            }
-            TyKind::AnonymousUnion(ref _fields, _recovered) => {
-                self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit();
-                hir::TyKind::Err
-            }
             TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
@@ -1493,12 +1358,11 @@ fn lower_opaque_impl_trait(
 
         let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
 
-        self.allocate_hir_id_counter(opaque_ty_node_id);
-
-        let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
+        let mut collected_lifetimes = Vec::new();
+        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
             let hir_bounds = lower_bounds(lctx);
 
-            let collected_lifetimes = lifetimes_from_impl_trait_bounds(
+            collected_lifetimes = lifetimes_from_impl_trait_bounds(
                 opaque_ty_node_id,
                 &hir_bounds,
                 capturable_lifetimes,
@@ -1513,7 +1377,7 @@ fn lower_opaque_impl_trait(
                         def_node_id,
                         DefPathData::LifetimeNs(name.ident().name),
                         ExpnId::root(),
-                        span,
+                        span.with_parent(None),
                     );
 
                     let (name, kind) = match name {
@@ -1551,9 +1415,7 @@ 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);
-
-            collected_lifetimes
+            lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
         });
 
         let lifetimes =
@@ -1575,7 +1437,7 @@ fn generate_opaque_type(
         opaque_ty_item: hir::OpaqueTy<'hir>,
         span: Span,
         opaque_ty_span: Span,
-    ) {
+    ) -> hir::OwnerNode<'hir> {
         let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
         // Generate an `type Foo = impl Trait;` declaration.
         trace!("registering opaque type with id {:#?}", opaque_ty_id);
@@ -1586,11 +1448,7 @@ fn generate_opaque_type(
             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
-        // automatically for all AST items. But this opaque type item
-        // does not actually exist in the AST.
-        self.insert_item(opaque_ty_item);
+        hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
     }
 
     fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
@@ -1659,7 +1517,7 @@ fn lower_fn_decl(
                 if let Some((_, ibty)) = &mut in_band_ty_params {
                     this.lower_ty_direct(
                         &param.ty,
-                        ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0),
+                        ImplTraitContext::Universal(ibty, this.current_hir_id_owner),
                     )
                 } else {
                     this.lower_ty_direct(&param.ty, ImplTraitContext::disallowed())
@@ -1752,8 +1610,6 @@ fn lower_async_fn_ret_ty(
 
         let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
 
-        self.allocate_hir_id_counter(opaque_ty_node_id);
-
         // When we create the opaque type for this async fn, it is going to have
         // to capture all the lifetimes involved in the signature (including in the
         // return type). This is done by introducing lifetime parameters for:
@@ -1802,7 +1658,8 @@ fn lower_async_fn_ret_ty(
         // grow.
         let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
 
-        let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| {
+        let mut lifetime_params = Vec::new();
+        self.with_hir_id_owner(opaque_ty_node_id, |this| {
             // We have to be careful to get elision right here. The
             // idea is that we create a lifetime parameter for each
             // lifetime in the return type.  So, given a return type
@@ -1824,7 +1681,7 @@ fn lower_async_fn_ret_ty(
             //
             // Note: this must be done after lowering the output type,
             // as the output type may introduce new in-band lifetimes.
-            let lifetime_params: Vec<(Span, ParamName)> = this
+            lifetime_params = this
                 .in_scope_lifetimes
                 .iter()
                 .cloned()
@@ -1853,9 +1710,7 @@ fn lower_async_fn_ret_ty(
             };
 
             trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
-            this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
-
-            lifetime_params
+            this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
         });
 
         // As documented above on the variable
index 90a22b5c209522864143e6b40c2d20f2fa12af5e..929f427484dba4ac28ba65fd7bf931c067c46376 100644 (file)
@@ -99,7 +99,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         num_lifetimes,
                         parenthesized_generic_args,
                         itctx.reborrow(),
-                        None,
                     )
                 },
             )),
@@ -147,7 +146,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 0,
                 ParenthesizedGenericArgs::Err,
                 itctx.reborrow(),
-                None,
             ));
             let qpath = hir::QPath::TypeRelative(ty, hir_segment);
 
@@ -178,7 +176,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         res: Res,
         p: &Path,
         param_mode: ParamMode,
-        explicit_owner: Option<NodeId>,
     ) -> &'hir hir::Path<'hir> {
         self.arena.alloc(hir::Path {
             res,
@@ -190,7 +187,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     0,
                     ParenthesizedGenericArgs::Err,
                     ImplTraitContext::disallowed(),
-                    explicit_owner,
                 )
             })),
             span: self.lower_span(p.span),
@@ -205,7 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     ) -> &'hir hir::Path<'hir> {
         let res = self.expect_full_res(id);
         let res = self.lower_res(res);
-        self.lower_path_extra(res, p, param_mode, None)
+        self.lower_path_extra(res, p, param_mode)
     }
 
     crate fn lower_path_segment(
@@ -216,7 +212,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         expected_lifetimes: usize,
         parenthesized_generic_args: ParenthesizedGenericArgs,
         itctx: ImplTraitContext<'_, 'hir>,
-        explicit_owner: Option<NodeId>,
     ) -> hir::PathSegment<'hir> {
         debug!(
             "path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
@@ -354,11 +349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let res = self.expect_full_res(segment.id);
-        let id = if let Some(owner) = explicit_owner {
-            self.lower_node_id_with_owner(segment.id, owner)
-        } else {
-            self.lower_node_id(segment.id)
-        };
+        let id = self.lower_node_id(segment.id);
         debug!(
             "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
             segment.ident, segment.id, id,
index 4a6eb80fb30ce1ed0bfc0ef92595d9520ba63876..9312a68bc600c15d75ff721b3088d4c4e56c006a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_ast_passes"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 itertools = "0.9"
index aca4503903c066e0cd3013401e913ee8a3a45098..24108f779c818529b674b0f1e42f91d032d99909 100644 (file)
@@ -193,11 +193,6 @@ fn walk_ty(&mut self, t: &'a Ty) {
                     }
                 }
             }
-            TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
-                self.with_banned_assoc_ty_bound(|this| {
-                    walk_list!(this, visit_struct_field_def, fields)
-                });
-            }
             _ => visit::walk_ty(self, t),
         }
     }
@@ -205,7 +200,6 @@ fn walk_ty(&mut self, t: &'a Ty) {
     fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
         if let Some(ident) = field.ident {
             if ident.name == kw::Underscore {
-                self.check_anonymous_field(field);
                 self.visit_vis(&field.vis);
                 self.visit_ident(ident);
                 self.visit_ty_common(&field.ty);
@@ -251,66 +245,6 @@ fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
         err.emit();
     }
 
-    fn check_anonymous_field(&self, field: &FieldDef) {
-        let FieldDef { ty, .. } = field;
-        match &ty.kind {
-            TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
-                // We already checked for `kw::Underscore` before calling this function,
-                // so skip the check
-            }
-            TyKind::Path(..) => {
-                // If the anonymous field contains a Path as type, we can't determine
-                // if the path is a valid struct or union, so skip the check
-            }
-            _ => {
-                let msg = "unnamed fields can only have struct or union types";
-                let label = "not a struct or union";
-                self.err_handler()
-                    .struct_span_err(field.span, msg)
-                    .span_label(ty.span, label)
-                    .emit();
-            }
-        }
-    }
-
-    fn deny_anonymous_struct(&self, ty: &Ty) {
-        match &ty.kind {
-            TyKind::AnonymousStruct(..) => {
-                self.err_handler()
-                    .struct_span_err(
-                        ty.span,
-                        "anonymous structs are not allowed outside of unnamed struct or union fields",
-                    )
-                    .span_label(ty.span, "anonymous struct declared here")
-                    .emit();
-            }
-            TyKind::AnonymousUnion(..) => {
-                self.err_handler()
-                    .struct_span_err(
-                        ty.span,
-                        "anonymous unions are not allowed outside of unnamed struct or union fields",
-                    )
-                    .span_label(ty.span, "anonymous union declared here")
-                    .emit();
-            }
-            _ => {}
-        }
-    }
-
-    fn deny_anonymous_field(&self, field: &FieldDef) {
-        if let Some(ident) = field.ident {
-            if ident.name == kw::Underscore {
-                self.err_handler()
-                    .struct_span_err(
-                        field.span,
-                        "anonymous fields are not allowed outside of structs or unions",
-                    )
-                    .span_label(ident.span, "anonymous field declared here")
-                    .emit()
-            }
-        }
-    }
-
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
@@ -422,11 +356,25 @@ fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
     }
 
     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
+        self.check_decl_num_args(fn_decl);
         self.check_decl_cvaradic_pos(fn_decl);
         self.check_decl_attrs(fn_decl);
         self.check_decl_self_param(fn_decl, self_semantic);
     }
 
+    /// Emits fatal error if function declaration has more than `u16::MAX` arguments
+    /// Error is fatal to prevent errors during typechecking
+    fn check_decl_num_args(&self, fn_decl: &FnDecl) {
+        let max_num_args: usize = u16::MAX.into();
+        if fn_decl.inputs.len() > max_num_args {
+            let Param { span, .. } = fn_decl.inputs[0];
+            self.err_handler().span_fatal(
+                span,
+                &format!("function can not have more than {} arguments", max_num_args),
+            );
+        }
+    }
+
     fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
         match &*fn_decl.inputs {
             [Param { ty, span, .. }] => {
@@ -1067,7 +1015,6 @@ fn visit_expr(&mut self, expr: &'a Expr) {
 
     fn visit_ty(&mut self, ty: &'a Ty) {
         self.visit_ty_common(ty);
-        self.deny_anonymous_struct(ty);
         self.walk_ty(ty)
     }
 
@@ -1082,7 +1029,6 @@ fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
     }
 
     fn visit_field_def(&mut self, s: &'a FieldDef) {
-        self.deny_anonymous_field(s);
         visit::walk_field_def(self, s)
     }
 
@@ -1655,7 +1601,9 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
                 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 =>
+                if self.in_const_trait_impl
+                    || ctxt == AssocCtxt::Trait
+                    || matches!(sig.header.constness, Const::Yes(_)) =>
             {
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
index 1defb65ed8793d9ef7142dcacee8935f5a95ec43..06e9d9ed329331e3d18e72d77ba7c45f2baea978 100644 (file)
@@ -668,7 +668,6 @@ macro_rules! gate_all {
         // involved, so we only emit errors where there are no other parsing errors.
         gate_all!(destructuring_assignment, "destructuring assignments are unstable");
     }
-    gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
@@ -703,10 +702,16 @@ macro_rules! gate_all {
 }
 
 fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
+    // checks if `#![feature]` has been used to enable any lang feature
+    // does not check the same for lib features unless there's at least one
+    // declared lang feature
     use rustc_errors::Applicability;
 
     if !sess.opts.unstable_features.is_nightly_build() {
         let lang_features = &sess.features_untracked().declared_lang_features;
+        if lang_features.len() == 0 {
+            return;
+        }
         for attr in krate.attrs.iter().filter(|attr| attr.has_name(sym::feature)) {
             let mut err = struct_span_err!(
                 sess.parse_sess.span_diagnostic,
index fa88740103ba3ed40f59f96d6fdb29ff87e20eab..29f2be4cf46486d4b46497edf6d0b715bad01d71 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_ast_pretty"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 3cf04be160c64a0a8003493187d618cbca4217a2..c24882086e12d16d1b808e6f4270adebd4820658 100644 (file)
@@ -985,14 +985,6 @@ pub fn print_type(&mut self, ty: &ast::Ty) {
                 }
                 self.pclose();
             }
-            ast::TyKind::AnonymousStruct(ref fields, ..) => {
-                self.head("struct");
-                self.print_record_struct_body(&fields, ty.span);
-            }
-            ast::TyKind::AnonymousUnion(ref fields, ..) => {
-                self.head("union");
-                self.print_record_struct_body(&fields, ty.span);
-            }
             ast::TyKind::Paren(ref typ) => {
                 self.popen();
                 self.print_type(typ);
@@ -1413,7 +1405,12 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
         }
     }
 
-    crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
+    crate fn print_record_struct_body(
+        &mut self,
+        fields: &Vec<ast::FieldDef>,
+        span: rustc_span::Span,
+    ) {
+        self.nbsp();
         self.bopen();
         self.hardbreak_if_not_bol();
 
@@ -1462,7 +1459,6 @@ fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) {
             }
             ast::VariantData::Struct(ref fields, ..) => {
                 self.print_where_clause(&generics.where_clause);
-                self.nbsp();
                 self.print_record_struct_body(fields, span);
             }
         }
index 0566379e1f5e1c39d05eab6702efd9199654dc64..ba310a6860e82386214c9205ac2f21aed3d52d89 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_attr"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index c683c388ba9ead0b7c939caade7db8e941eb5bb9..75e9c69af4e5c9d8bfab4a5963c327ee46ab03e0 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_borrowck"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index f6e4e3888418fb22d848f7b63f1ebf6a7b13a5ec..4333038a6f936618c6f683dd6b4230fbd104a15a 100644 (file)
@@ -14,7 +14,9 @@
 };
 
 /// This function computes Polonius facts for the given body. It makes a copy of
-/// the body because it needs to regenerate the region identifiers.
+/// the body because it needs to regenerate the region identifiers. This function
+/// should never be invoked during a typical compilation session due to performance
+/// issues with Polonius.
 ///
 /// Note:
 /// *   This function will panic if the required body was already stolen. This
@@ -22,8 +24,6 @@
 ///     because they are evaluated during typechecking. The panic can be avoided
 ///     by overriding the `mir_borrowck` query. You can find a complete example
 ///     that shows how to do this at `src/test/run-make/obtain-borrowck/`.
-/// *   This function will also panic if computation of Polonius facts
-///     (`-Zpolonius` flag) is not enabled.
 ///
 /// *   Polonius is highly unstable, so expect regular changes in its signature or other details.
 pub fn get_body_with_borrowck_facts<'tcx>(
index ce1e7c14b1ff673b249fd3bc4fca294296c28403..f4cbbb60b053a2625f1c4578c96545d09a04a53c 100644 (file)
@@ -218,7 +218,19 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                             );
                             if self.fn_self_span_reported.insert(fn_span) {
                                 err.span_note(
-                                    self_arg.span,
+                                    // Check whether the source is accessible
+                                    if self
+                                        .infcx
+                                        .tcx
+                                        .sess
+                                        .source_map()
+                                        .span_to_snippet(self_arg.span)
+                                        .is_ok()
+                                    {
+                                        self_arg.span
+                                    } else {
+                                        fn_call_span
+                                    },
                                     "calling this operator moves the left-hand side",
                                 );
                             }
@@ -429,7 +441,10 @@ pub(crate) fn report_use_of_moved_or_uninitialized(
                     deref_target_ty
                 ));
 
-                err.span_note(deref_target, "deref defined here");
+                // Check first whether the source is accessible (issue #87060)
+                if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
+                    err.span_note(deref_target, "deref defined here");
+                }
             }
 
             if let Some((_, mut old_err)) =
index 3c11408458629dfe84b6bb40ef6e05cfa38f9db7..b23ce281bef24de4ed1b6ef045744f2ff25bcb95 100644 (file)
@@ -336,15 +336,15 @@ fn report_cannot_move_from_borrowed_content(
                 if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() =>
             {
                 let closure_kind_ty = closure_substs.as_closure().kind_ty();
-                let closure_kind = closure_kind_ty.to_opt_closure_kind();
-                let capture_description = match closure_kind {
-                    Some(ty::ClosureKind::Fn) => "captured variable in an `Fn` closure",
-                    Some(ty::ClosureKind::FnMut) => "captured variable in an `FnMut` closure",
+                let closure_kind = match closure_kind_ty.to_opt_closure_kind() {
+                    Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind,
                     Some(ty::ClosureKind::FnOnce) => {
                         bug!("closure kind does not match first argument type")
                     }
                     None => bug!("closure kind not inferred by borrowck"),
                 };
+                let capture_description =
+                    format!("captured variable in an `{}` closure", closure_kind);
 
                 let upvar = &self.upvars[upvar_field.unwrap().index()];
                 let upvar_hir_id = upvar.place.get_root_variable();
@@ -368,6 +368,10 @@ fn report_cannot_move_from_borrowed_content(
                 let mut diag = self.cannot_move_out_of(span, &place_description);
 
                 diag.span_label(upvar_span, "captured outer variable");
+                diag.span_label(
+                    self.body.span,
+                    format!("captured by this `{}` closure", closure_kind),
+                );
 
                 diag
             }
index 57d2a3c5ce91bba441d81ad723ddcc02f02788fb..0761d63c665402a589b483d18391f98beac93e5f 100644 (file)
@@ -40,6 +40,7 @@ fn description(&self) -> &'static str {
             ConstraintCategory::CopyBound => "copying this value ",
             ConstraintCategory::OpaqueType => "opaque type ",
             ConstraintCategory::ClosureUpvar(_) => "closure capture ",
+            ConstraintCategory::Usage => "this usage ",
             ConstraintCategory::Boring
             | ConstraintCategory::BoringNoLocation
             | ConstraintCategory::Internal => "",
index 4e4b8a953cd1228c177dc07f90b45a2ea6464069..b3b7d7e02ccef068b444607116f3058a20ba0f10 100644 (file)
@@ -154,11 +154,6 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     debug!("do_mir_borrowck(def = {:?})", def);
 
-    assert!(
-        !return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius,
-        "borrowck facts can be requested only when Polonius is enabled"
-    );
-
     let tcx = infcx.tcx;
     let param_env = tcx.param_env(def.did);
     let id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -235,6 +230,8 @@ fn do_mir_borrowck<'a, 'tcx>(
     let borrow_set =
         Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
 
+    let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius;
+
     // Compute non-lexical lifetimes.
     let nll::NllOutput {
         regioncx,
@@ -254,6 +251,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         &mdpe.move_data,
         &borrow_set,
         &upvars,
+        use_polonius,
     );
 
     // Dump MIR results into a file, if that is enabled. This let us
index 8b2c0362261ca9ac4e6aacac8c979e221933a203..477b049b07596cda7b1c7eed0399d82fdf7938cb 100644 (file)
@@ -164,8 +164,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     upvars: &[Upvar<'tcx>],
+    use_polonius: bool,
 ) -> NllOutput<'tcx> {
-    let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
+    let mut all_facts =
+        (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
 
     let universal_regions = Rc::new(universal_regions);
 
@@ -281,7 +283,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
             all_facts.write_to_dir(dir_path, location_table).unwrap();
         }
 
-        if infcx.tcx.sess.opts.debugging_opts.polonius {
+        if use_polonius {
             let algorithm =
                 env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
index 48e45a9b1ce72e7f1559df69e847f627d7bb4e0c..128faab8d722e204e189031a418ca24407465c53 100644 (file)
@@ -85,7 +85,7 @@ pub struct RegionInferenceContext<'tcx> {
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
     /// Map universe indexes to information on why we created it.
-    universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+    universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
@@ -256,7 +256,7 @@ pub(crate) fn new(
             Location,
             FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
         >,
-        universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+        universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
         elements: &Rc<RegionValueElements>,
@@ -1739,7 +1739,7 @@ fn check_member_constraints(
                     category: constraint.category,
                     from_closure: false,
                     span,
-                    variance_info: constraint.variance_info.clone(),
+                    variance_info: constraint.variance_info,
                 };
             }
             Locations::Single(loc) => loc,
@@ -1752,13 +1752,13 @@ fn check_member_constraints(
                 category,
                 from_closure: true,
                 span: span,
-                variance_info: constraint.variance_info.clone(),
+                variance_info: constraint.variance_info,
             })
             .unwrap_or(BlameConstraint {
                 category: constraint.category,
                 from_closure: false,
                 span: body.source_info(loc).span,
-                variance_info: constraint.variance_info.clone(),
+                variance_info: constraint.variance_info,
             })
     }
 
@@ -2001,7 +2001,7 @@ fn check_member_constraints(
                         category: constraint.category,
                         from_closure: false,
                         span: constraint.locations.span(body),
-                        variance_info: constraint.variance_info.clone(),
+                        variance_info: constraint.variance_info,
                     }
                 }
             })
@@ -2149,7 +2149,7 @@ fn check_member_constraints(
     }
 
     crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        self.universe_causes[universe].clone()
+        self.universe_causes[&universe].clone()
     }
 }
 
index 39b83e5043101bbde09f54f02f7f1862dc3c7b43..d790e31105c8aa2f2ee20c82662dce9c1a473959 100644 (file)
@@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
     /// which has no `external_name` in which case we use `'empty` as the
     /// region to pass to `infer_opaque_definition_from_instantiation`.
-    #[instrument(skip(self, infcx))]
+    #[instrument(level = "debug", skip(self, infcx))]
     pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
index 7a8c0a3da1f1f4854370e6982b9243463fe3a69a..18070164e82195f7430c297fe9926b07f86f5f15 100644 (file)
@@ -50,9 +50,10 @@ pub(super) fn fully_perform_op<R, Op>(
                 None => UniverseInfo::other(),
             };
             for u in old_universe..universe {
-                let info_universe =
-                    self.borrowck_context.constraints.universe_causes.push(universe_info.clone());
-                assert_eq!(u.as_u32() + 1, info_universe.as_u32());
+                self.borrowck_context
+                    .constraints
+                    .universe_causes
+                    .insert(u + 1, universe_info.clone());
             }
         }
 
@@ -70,9 +71,12 @@ pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
         let (instantiated, _) =
             self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
 
-        for _ in 0..canonical.max_universe.as_u32() {
+        for u in 0..canonical.max_universe.as_u32() {
             let info = UniverseInfo::other();
-            self.borrowck_context.constraints.universe_causes.push(info);
+            self.borrowck_context
+                .constraints
+                .universe_causes
+                .insert(ty::UniverseIndex::from_u32(u), info);
         }
 
         instantiated
index e1e8f6a61adb817038607d3c103394d97c29e531..70c74940d6235e117b8400a96d8d6eba851f643a 100644 (file)
@@ -259,7 +259,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // 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
+                let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
@@ -286,8 +286,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
-                let constraints_implied_2 = self.add_implied_bounds(ty);
-                normalized_inputs_and_output.push(ty);
+                let constraints_implied_2 =
+                    if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+                normalized_inputs_and_output.push(norm_ty);
                 constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
             })
             .collect();
index 9d6f6f60a94f91976edabb4f5c5174614750cb49..46d30a188edb903ecfd6b2b5b235ef4f155d38dc 100644 (file)
@@ -194,6 +194,8 @@ fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span:
                     b
                 }
             };
+            // Note: if we have to introduce new placeholders during normalization above, then we won't have
+            // added those universes to the universe info, which we would want in `relate_tys`.
             if let Err(terr) =
                 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
             {
index 2c8ff45b00da43813b3f3768bfb734df884d7a86..5ccf380602554bfed8eb5c3b2b75b24f489861a8 100644 (file)
@@ -136,6 +136,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
     upvars: &[Upvar<'tcx>],
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+    let mut universe_causes = FxHashMap::default();
+    universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
@@ -144,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
         member_constraints: MemberConstraintSet::default(),
         closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
-        universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1),
+        universe_causes,
     };
 
     let CreateResult {
@@ -159,9 +161,9 @@ pub(crate) fn type_check<'mir, 'tcx>(
         &mut constraints,
     );
 
-    for _ in ty::UniverseIndex::ROOT..infcx.universe() {
+    for u in ty::UniverseIndex::ROOT..infcx.universe() {
         let info = UniverseInfo::other();
-        constraints.universe_causes.push(info);
+        constraints.universe_causes.insert(u, info);
     }
 
     let mut borrowck_context = BorrowCheckContext {
@@ -924,7 +926,7 @@ struct BorrowCheckContext<'a, 'tcx> {
     crate closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
-    crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+    crate universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     crate type_tests: Vec<TypeTest<'tcx>>,
 }
@@ -1386,11 +1388,24 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo
                             ConstraintCategory::Return(ReturnConstraint::Normal)
                         }
                     }
+                    Some(l)
+                        if matches!(
+                            body.local_decls[l].local_info,
+                            Some(box LocalInfo::AggregateTemp)
+                        ) =>
+                    {
+                        ConstraintCategory::Usage
+                    }
                     Some(l) if !body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
                 };
+                debug!(
+                    "assignment category: {:?} {:?}",
+                    category,
+                    place.as_local().map(|l| &body.local_decls[l])
+                );
 
                 let place_ty = place.ty(body, tcx).ty;
                 let place_ty = self.normalize(place_ty, location);
@@ -1996,7 +2011,6 @@ fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: L
                                     &obligation,
                                     &traits::SelectionError::Unimplemented,
                                     false,
-                                    false,
                                 );
                             }
                         }
index 0b9c33ccb775a96ad7fe411259aaa6ba7bbd609e..de86d39cc3722e41b3ed67068269598d3da7220e 100644 (file)
@@ -80,10 +80,11 @@ fn param_env(&self) -> ty::ParamEnv<'tcx> {
     }
 
     fn create_next_universe(&mut self) -> ty::UniverseIndex {
-        let info_universe =
-            self.borrowck_context.constraints.universe_causes.push(self.universe_info.clone());
         let universe = self.infcx.create_next_universe();
-        assert_eq!(info_universe, universe);
+        self.borrowck_context
+            .constraints
+            .universe_causes
+            .insert(universe, self.universe_info.clone());
         universe
     }
 
index 2370ac201b0182b7211f4c8e5de65dc5bcae124d..fd34f947f72c0eec04edab81c958efab63234d19 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_builtin_macros"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 652165fb9b60b1f646c7827aaa07d17548a6e8a1..c032364c008f34a551f782107b3eb7594a843884 100644 (file)
@@ -117,6 +117,10 @@ fn parse_args<'a>(
         let mut explicit_reg = false;
         let op = if !is_global_asm && p.eat_keyword(kw::In) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             ast::InlineAsmOperand::In { reg, expr }
         } else if !is_global_asm && p.eat_keyword(sym::out) {
@@ -129,6 +133,10 @@ fn parse_args<'a>(
             ast::InlineAsmOperand::Out { reg, expr, late: true }
         } else if !is_global_asm && p.eat_keyword(sym::inout) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             if p.eat(&token::FatArrow) {
                 let out_expr =
@@ -139,6 +147,10 @@ fn parse_args<'a>(
             }
         } else if !is_global_asm && p.eat_keyword(sym::inlateout) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             if p.eat(&token::FatArrow) {
                 let out_expr =
@@ -510,7 +522,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
             match expr_to_spanned_string(ecx, template_expr, msg) {
                 Ok(template_part) => template_part,
                 Err(err) => {
-                    if let Some(mut err) = err {
+                    if let Some((mut err, _)) = err {
                         err.emit();
                     }
                     return None;
index 14506f296bf95d294964445da692c648ceceacdc..ecf70da6d96c58d6e1b73c5edc2c3167c6655e45 100644 (file)
@@ -65,15 +65,29 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
+    let fmt = substr.nonself_args[0].clone();
+
+    // Special fast path for unit variants. In the common case of an enum that is entirely unit
+    // variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in
+    // favor of a lookup table.
+    if let ast::VariantData::Unit(..) = vdata {
+        let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
+        let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
+        let stmts = vec![cx.stmt_expr(expr)];
+        let block = cx.block(span, stmts);
+        return cx.expr_block(block);
+    }
+
     let builder = Ident::new(sym::debug_trait_builder, span);
     let builder_expr = cx.expr_ident(span, builder);
 
-    let fmt = substr.nonself_args[0].clone();
-
     let mut stmts = Vec::with_capacity(fields.len() + 2);
     let fn_path_finish;
     match vdata {
-        ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+        ast::VariantData::Unit(..) => {
+            cx.span_bug(span, "unit variants should have been handled above");
+        }
+        ast::VariantData::Tuple(..) => {
             // tuple struct/"normal" variant
             let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
             let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
index 8508b3b7ae6edb9a273d9f05e16950b75096e030..c7626dec4d7c0b29bc5c07efb1f0f2c1a0154906 100644 (file)
@@ -964,17 +964,19 @@ pub fn expand_preparsed_format_args(
         }
         Ok(fmt) => fmt,
         Err(err) => {
-            if let Some(mut err) = err {
+            if let Some((mut err, suggested)) = err {
                 let sugg_fmt = match args.len() {
                     0 => "{}".to_string(),
                     _ => format!("{}{{}}", "{} ".repeat(args.len())),
                 };
-                err.span_suggestion(
-                    fmt_sp.shrink_to_lo(),
-                    "you might be missing a string literal to format with",
-                    format!("\"{}\", ", sugg_fmt),
-                    Applicability::MaybeIncorrect,
-                );
+                if !suggested {
+                    err.span_suggestion(
+                        fmt_sp.shrink_to_lo(),
+                        "you might be missing a string literal to format with",
+                        format!("\"{}\", ", sugg_fmt),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
                 err.emit();
             }
             return DummyResult::raw_expr(sp, true);
index 6f40fc0fcb881e77fa67e548191d380321f70550..61d40702a32842d2769040023e6a59f0c1c2fcc3 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_codegen_cranelift"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 crate-type = ["dylib"]
index 13790409e59f633f28292f8e2c3709f189e37806..15bb90678059daa9be2156909d3b127a9805dfb1 100644 (file)
@@ -5,7 +5,7 @@
 mod returning;
 
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
 use rustc_target::abi::call::{Conv, FnAbi};
 use rustc_target::spec::abi::Abi;
 
@@ -53,7 +53,11 @@ pub(crate) fn get_function_sig<'tcx>(
     inst: Instance<'tcx>,
 ) -> Signature {
     assert!(!inst.substs.needs_infer());
-    clif_sig_from_fn_abi(tcx, triple, &FnAbi::of_instance(&RevealAllLayoutCx(tcx), inst, &[]))
+    clif_sig_from_fn_abi(
+        tcx,
+        triple,
+        &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
+    )
 }
 
 /// Instance must be monomorphized
@@ -350,14 +354,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
     };
 
     let extra_args = &args[fn_sig.inputs().len()..];
-    let extra_args = extra_args
-        .iter()
-        .map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx)))
-        .collect::<Vec<_>>();
+    let extra_args = fx
+        .tcx
+        .mk_type_list(extra_args.iter().map(|op_arg| fx.monomorphize(op_arg.ty(fx.mir, fx.tcx))));
     let fn_abi = if let Some(instance) = instance {
-        FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), instance, &extra_args)
+        RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(instance, extra_args)
     } else {
-        FnAbi::of_fn_ptr(&RevealAllLayoutCx(fx.tcx), fn_ty.fn_sig(fx.tcx), &extra_args)
+        RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_ty.fn_sig(fx.tcx), extra_args)
     };
 
     let is_cold = instance
@@ -525,7 +528,8 @@ pub(crate) fn codegen_drop<'tcx>(
                     def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
                     substs: drop_instance.substs,
                 };
-                let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), virtual_drop, &[]);
+                let fn_abi =
+                    RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
 
                 let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
                 let sig = fx.bcx.import_signature(sig);
@@ -534,7 +538,8 @@ pub(crate) fn codegen_drop<'tcx>(
             _ => {
                 assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
 
-                let fn_abi = FnAbi::of_instance(&RevealAllLayoutCx(fx.tcx), drop_instance, &[]);
+                let fn_abi =
+                    RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(drop_instance, ty::List::empty());
 
                 let arg_value = drop_place.place_ref(
                     fx,
index 44eae706ea8f6df56448214f8afab5383bc67ade..2144e7ed67acbc75a7e4ca0c3781e27148f5294c 100644 (file)
@@ -92,9 +92,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> {
         match self.mode {
             PassMode::Ignore => smallvec![],
-            PassMode::Direct(attrs) => match &self.layout.abi {
+            PassMode::Direct(attrs) => match self.layout.abi {
                 Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
-                    AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())),
+                    AbiParam::new(scalar_to_clif_type(tcx, scalar)),
                     attrs
                 )],
                 Abi::Vector { .. } => {
@@ -103,10 +103,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
             },
-            PassMode::Pair(attrs_a, attrs_b) => match &self.layout.abi {
+            PassMode::Pair(attrs_a, attrs_b) => match self.layout.abi {
                 Abi::ScalarPair(a, b) => {
-                    let a = scalar_to_clif_type(tcx, a.clone());
-                    let b = scalar_to_clif_type(tcx, b.clone());
+                    let a = scalar_to_clif_type(tcx, a);
+                    let b = scalar_to_clif_type(tcx, b);
                     smallvec![
                         apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a),
                         apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
@@ -139,9 +139,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
         match self.mode {
             PassMode::Ignore => (None, vec![]),
-            PassMode::Direct(_) => match &self.layout.abi {
+            PassMode::Direct(_) => match self.layout.abi {
                 Abi::Scalar(scalar) => {
-                    (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))])
+                    (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
                 }
                 Abi::Vector { .. } => {
                     let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
@@ -149,10 +149,10 @@ fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>)
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
             },
-            PassMode::Pair(_, _) => match &self.layout.abi {
+            PassMode::Pair(_, _) => match self.layout.abi {
                 Abi::ScalarPair(a, b) => {
-                    let a = scalar_to_clif_type(tcx, a.clone());
-                    let b = scalar_to_clif_type(tcx, b.clone());
+                    let a = scalar_to_clif_type(tcx, a);
+                    let b = scalar_to_clif_type(tcx, b);
                     (None, vec![AbiParam::new(a), AbiParam::new(b)])
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
index 46a7485e4ef9ce2e0a7d859a1fa240c17fcaa39f..d8fa2c769046827fa36c332f1e5d71047ef68507 100644 (file)
@@ -3,8 +3,7 @@
 use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::adjustment::PointerCast;
-use rustc_middle::ty::layout::FnAbiExt;
-use rustc_target::abi::call::FnAbi;
+use rustc_middle::ty::layout::FnAbiOf;
 
 use crate::constant::ConstantCx;
 use crate::prelude::*;
@@ -62,7 +61,7 @@ pub(crate) fn codegen_fn<'tcx>(
         instance,
         symbol_name,
         mir,
-        fn_abi: Some(FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
+        fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
 
         bcx,
         block_map,
@@ -726,15 +725,20 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
                     let ptr = fx.bcx.inst_results(call)[0];
                     lval.write_cvalue(fx, CValue::by_val(ptr, box_layout));
                 }
-                Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
+                Rvalue::NullaryOp(null_op, ty) => {
                     assert!(
                         lval.layout()
                             .ty
                             .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
                     );
-                    let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes();
+                    let layout = fx.layout_of(fx.monomorphize(ty));
+                    let val = match null_op {
+                        NullOp::SizeOf => layout.size.bytes(),
+                        NullOp::AlignOf => layout.align.abi.bytes(),
+                        NullOp::Box => unreachable!(),
+                    };
                     let val =
-                        CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
+                        CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
                     lval.write_cvalue(fx, val);
                 }
                 Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() {
index e7cd5edbbf654a2888e6b0ba4965da554f37f4a1..89e0cb8d90ecd6c58bef18c764a66f9cc59b8654 100644 (file)
@@ -8,7 +8,6 @@
 
 #![feature(rustc_private)]
 
-extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_interface;
 extern crate rustc_session;
index 6f7ca51d038c0155233e9ad8dcea64cfa70a6b47..0e84681d9ad94f4c40db9dcff7854c22f6017dd9 100644 (file)
@@ -1,5 +1,7 @@
 use rustc_index::vec::IndexVec;
-use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers};
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
+};
 use rustc_middle::ty::SymbolName;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
@@ -239,7 +241,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
     pub(crate) instance: Instance<'tcx>,
     pub(crate) symbol_name: SymbolName<'tcx>,
     pub(crate) mir: &'tcx Body<'tcx>,
-    pub(crate) fn_abi: Option<FnAbi<'tcx, Ty<'tcx>>>,
+    pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
 
     pub(crate) bcx: FunctionBuilder<'clif>,
     pub(crate) block_map: IndexVec<BasicBlock, Block>,
@@ -266,6 +268,20 @@ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) ->
     }
 }
 
+impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
+    }
+}
+
 impl<'tcx> layout::HasTyCtxt<'tcx> for FunctionCx<'_, '_, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.tcx
@@ -378,6 +394,43 @@ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) ->
     }
 }
 
+impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+            self.0.sess.span_fatal(span, &err.to_string())
+        } else {
+            match fn_abi_request {
+                FnAbiRequest::OfFnPtr { sig, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+                        sig,
+                        extra_args,
+                        err
+                    );
+                }
+                FnAbiRequest::OfInstance { instance, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_instance({}, {:?})` failed: {}",
+                        instance,
+                        extra_args,
+                        err
+                    );
+                }
+            }
+        }
+    }
+}
+
 impl<'tcx> layout::HasTyCtxt<'tcx> for RevealAllLayoutCx<'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.0
index 424a0d742d12b56c29b4b40339faedb7d6b204dd..5c4991f1fb667382809dc2bfc00896653a75072e 100644 (file)
@@ -129,9 +129,7 @@ pub(crate) fn codegen_constant<'tcx>(
     };
     let const_val = match const_.val {
         ConstKind::Value(const_val) => const_val,
-        ConstKind::Unevaluated(uv)
-            if fx.tcx.is_static(uv.def.did) =>
-        {
+        ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
             assert!(uv.substs(fx.tcx).is_empty());
             assert!(uv.promoted.is_none());
 
index 12f61e0c564aab39944b735e7d4f34057a8df842..48183b2d4f634ee8945c66aab6d66ec6f0adeda2 100644 (file)
 }
 
 pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
-    let (element, count) = match &layout.abi {
-        Abi::Vector { element, count } => (element.clone(), *count),
+    let (element, count) = match layout.abi {
+        Abi::Vector { element, count } => (elementcount),
         _ => unreachable!(),
     };
 
@@ -823,7 +823,7 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value {
             dest.write_cvalue(fx, val);
         };
 
-        pref_align_of | min_align_of | needs_drop | type_id | type_name | variant_count, () {
+        pref_align_of | needs_drop | type_id | type_name | variant_count, () {
             let const_val =
                 fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap();
             let val = crate::constant::codegen_const_value(
index 05db74745a1c0583bb5598e885ac04e8eda37c64..ec846d71960b89863e7cb49e0d9eddf30d5a04fe 100644 (file)
@@ -61,9 +61,8 @@
     write::{FuncWriter, PlainWriter},
 };
 
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
 use rustc_session::config::OutputType;
-use rustc_target::abi::call::FnAbi;
 
 use crate::prelude::*;
 
@@ -81,7 +80,10 @@ pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
             vec![
                 format!("symbol {}", tcx.symbol_name(instance).name),
                 format!("instance {:?}", instance),
-                format!("abi {:?}", FnAbi::of_instance(&RevealAllLayoutCx(tcx), instance, &[])),
+                format!(
+                    "abi {:?}",
+                    RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())
+                ),
                 String::new(),
             ]
         } else {
index 364b3da92b88822fe614904ce75ed44582d2a288..30d5340935f14d90ea4773316340420a2fa11334 100644 (file)
@@ -49,11 +49,7 @@ fn codegen_field<'tcx>(
     }
 }
 
-fn scalar_pair_calculate_b_offset(
-    tcx: TyCtxt<'_>,
-    a_scalar: &Scalar,
-    b_scalar: &Scalar,
-) -> Offset32 {
+fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 {
     let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
     Offset32::new(b_offset.bytes().try_into().unwrap())
 }
@@ -124,12 +120,10 @@ pub(crate) fn load_scalar(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> Value {
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
                 let clif_ty = match layout.abi {
-                    Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
-                    Abi::Vector { ref element, count } => {
-                        scalar_to_clif_type(fx.tcx, element.clone())
-                            .by(u16::try_from(count).unwrap())
-                            .unwrap()
-                    }
+                    Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
+                    Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
+                        .by(u16::try_from(count).unwrap())
+                        .unwrap(),
                     _ => unreachable!("{:?}", layout.ty),
                 };
                 let mut flags = MemFlags::new();
@@ -147,13 +141,13 @@ pub(crate) fn load_scalar_pair(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> (Valu
         let layout = self.1;
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
-                let (a_scalar, b_scalar) = match &layout.abi {
+                let (a_scalar, b_scalar) = match layout.abi {
                     Abi::ScalarPair(a, b) => (a, b),
                     _ => unreachable!("load_scalar_pair({:?})", self),
                 };
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
-                let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
-                let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
+                let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar);
+                let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
                 let mut flags = MemFlags::new();
                 flags.set_notrap();
                 let val1 = ptr.load(fx, clif_ty1, flags);
@@ -564,7 +558,7 @@ fn transmute_value<'tcx>(
                 to_ptr.store(fx, val, flags);
                 return;
             }
-            Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
+            Abi::ScalarPair(a_scalar, b_scalar) => {
                 let (value, extra) = from.load_scalar_pair(fx);
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
                 to_ptr.store(fx, value, flags);
index 521ce344180a1063fdbee45863a2c64df17b07d3..3f02443458188caf558798b62cafee72ef154454 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_codegen_llvm"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 test = false
@@ -16,6 +16,7 @@ snap = "1"
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
 rustc-demangle = "0.1.21"
+rustc_arena = { path = "../rustc_arena" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
index cd55a61cbaf9d7b4c7675d73ff985a4478cf9fcf..1a0a3a0c340fa2bc4c43a84a5c74f597481ec8bd 100644 (file)
@@ -511,7 +511,12 @@ fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
     }
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
-        // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
+        if self.ret.layout.abi.is_uninhabited() {
+            llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite);
+        }
+        if !self.can_unwind {
+            llvm::Attribute::NoUnwind.apply_callsite(llvm::AttributePlace::Function, callsite);
+        }
 
         let mut i = 0;
         let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| {
@@ -536,16 +541,13 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
             }
             _ => {}
         }
-        if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
+        if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
             // If the value is a boolean, the range is 0..2 and that ultimately
             // become 0..0 when the type becomes i1, which would be rejected
             // by the LLVM verifier.
             if let Int(..) = scalar.value {
-                if !scalar.is_bool() {
-                    let range = scalar.valid_range_exclusive(bx);
-                    if range.start != range.end {
-                        bx.range_metadata(callsite, range);
-                    }
+                if !scalar.is_bool() && !scalar.is_always_valid(bx) {
+                    bx.range_metadata(callsite, scalar.valid_range);
                 }
             }
         }
index e0d312727a57df3b48807229b5d66030238e9a37..9690ad8b24603a17490099c9218d7d414f49dee3 100644 (file)
@@ -792,7 +792,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
 
 /// Helper function to get the LLVM type for a Scalar. Pointers are returned as
 /// the equivalent integer type.
-fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: &Scalar) -> &'ll Type {
+fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type {
     match scalar.value {
         Primitive::Int(Integer::I8, _) => cx.type_i8(),
         Primitive::Int(Integer::I16, _) => cx.type_i16(),
@@ -812,7 +812,7 @@ fn llvm_fixup_input(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Value {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
@@ -835,7 +835,7 @@ fn llvm_fixup_input(
             Abi::Vector { element, count },
         ) if layout.size.bytes() == 8 => {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
-            let vec_ty = bx.cx.type_vector(elem_ty, *count);
+            let vec_ty = bx.cx.type_vector(elem_ty, count);
             let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
@@ -890,7 +890,7 @@ fn llvm_fixup_output(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Value {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 bx.extract_element(value, bx.const_i32(0))
@@ -910,8 +910,8 @@ fn llvm_fixup_output(
             Abi::Vector { element, count },
         ) if layout.size.bytes() == 8 => {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
-            let vec_ty = bx.cx.type_vector(elem_ty, *count * 2);
-            let indices: Vec<_> = (0..*count).map(|x| bx.const_i32(x as i32)).collect();
+            let vec_ty = bx.cx.type_vector(elem_ty, count * 2);
+            let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
         (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
@@ -965,7 +965,7 @@ fn llvm_fixup_output_type(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Type {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 cx.type_vector(cx.type_i8(), 8)
index 56b93f83466805d32302878c4fbfa5923ae71f4f..51c70f0868f2697571943a4366d01e38506f9e9f 100644 (file)
@@ -305,9 +305,12 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
     let mut function_features = codegen_fn_attrs
         .target_features
         .iter()
-        .map(|f| {
+        .flat_map(|f| {
             let feature = &f.as_str();
-            format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+            llvm_util::to_llvm_feature(cx.tcx.sess, feature)
+                .into_iter()
+                .map(|f| format!("+{}", f))
+                .collect::<Vec<String>>()
         })
         .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
             InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
index da24fe08f0dfd6b7349e5290c27b216671de7678..dab7d3eaa8cfd45c6de1c95c831941e8f219920a 100644 (file)
 use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout,
+};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
-use rustc_target::abi::{self, Align, Size};
+use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ffi::CStr;
 use std::iter;
-use std::ops::{Deref, Range};
+use std::ops::Deref;
 use std::ptr;
 use tracing::debug;
 
@@ -97,6 +99,20 @@ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) ->
     }
 }
 
+impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        self.cx.handle_fn_abi_err(err, span, fn_abi_request)
+    }
+}
+
 impl Deref for Builder<'_, 'll, 'tcx> {
     type Target = CodegenCx<'ll, 'tcx>;
 
@@ -382,7 +398,7 @@ fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
             val
         }
     }
-    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value {
+    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
         if scalar.is_bool() {
             return self.trunc(val, self.cx().type_i1());
         }
@@ -460,16 +476,15 @@ fn load_operand(&mut self, place: PlaceRef<'tcx, &'ll Value>) -> OperandRef<'tcx
         fn scalar_load_metadata<'a, 'll, 'tcx>(
             bx: &mut Builder<'a, 'll, 'tcx>,
             load: &'ll Value,
-            scalar: &abi::Scalar,
+            scalar: abi::Scalar,
         ) {
             match scalar.value {
                 abi::Int(..) => {
-                    let range = scalar.valid_range_exclusive(bx);
-                    if range.start != range.end {
-                        bx.range_metadata(load, range);
+                    if !scalar.is_always_valid(bx) {
+                        bx.range_metadata(load, scalar.valid_range);
                     }
                 }
-                abi::Pointer if !scalar.valid_range.contains_zero() => {
+                abi::Pointer if !scalar.valid_range.contains(0) => {
                     bx.nonnull_metadata(load);
                 }
                 _ => {}
@@ -489,17 +504,17 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
             }
             let llval = const_llval.unwrap_or_else(|| {
                 let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
-                if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
+                if let abi::Abi::Scalar(scalar) = place.layout.abi {
                     scalar_load_metadata(self, load, scalar);
                 }
                 load
             });
             OperandValue::Immediate(self.to_immediate(llval, place.layout))
-        } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
+        } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi {
             let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
             let pair_ty = place.layout.llvm_type(self);
 
-            let mut load = |i, scalar: &abi::Scalar, align| {
+            let mut load = |i, scalar: abi::Scalar, align| {
                 let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
                 let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
                 let load = self.load(llty, llptr, align);
@@ -555,7 +570,7 @@ fn write_operand_repeatedly(
         next_bx
     }
 
-    fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
+    fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) {
         if self.sess().target.arch == "amdgpu" {
             // amdgpu/LLVM does something weird and thinks an i64 value is
             // split into a v2i32, halving the bitwidth LLVM expects,
@@ -568,7 +583,7 @@ fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
             let llty = self.cx.val_ty(load);
             let v = [
                 self.cx.const_uint_big(llty, range.start),
-                self.cx.const_uint_big(llty, range.end),
+                self.cx.const_uint_big(llty, range.end.wrapping_add(1)),
             ];
 
             llvm::LLVMSetMetadata(
index bb16c90cd12f1ca0932a62e99b8635bfd1f97cd6..a96ba148a6ce30f7374b2a36086401bd09e30597 100644 (file)
@@ -4,7 +4,7 @@
 //! and methods are represented as just a fn ptr and not a full
 //! closure.
 
-use crate::abi::{FnAbi, FnAbiLlvmExt};
+use crate::abi::FnAbiLlvmExt;
 use crate::attributes;
 use crate::context::CodegenCx;
 use crate::llvm;
@@ -12,7 +12,7 @@
 use rustc_codegen_ssa::traits::*;
 use tracing::debug;
 
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
 
 /// Codegens a reference to a fn/method item, monomorphizing and
@@ -42,7 +42,7 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
         sym
     );
 
-    let fn_abi = FnAbi::of_instance(cx, instance, &[]);
+    let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
 
     let llfn = if let Some(llfn) = cx.get_declared_value(&sym) {
         // Create a fn pointer with the new signature.
index cee582aec95ebf077b818093c990d77044451c07..73a8d4644316346c3347da6ed857777521f089c1 100644 (file)
@@ -228,7 +228,7 @@ fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> {
         })
     }
 
-    fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value {
+    fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value {
         let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
         match cv {
             Scalar::Int(ScalarInt::ZST) => {
index e673b06f1552795b6b65ec64abf335a9ba20ded7..ef3a90fdecaaa7874479e8659119ba69416e7050 100644 (file)
@@ -111,7 +111,7 @@ fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
                 Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
                 &cx.tcx,
             ),
-            &Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
+            Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
             cx.type_i8p_ext(address_space),
         ));
         next_offset = offset + pointer_size;
index 2d397dc58353402fe76e6b4925e376176376a071..52a12b2fd81d8b16ebfd8cc73467965437f3d388 100644 (file)
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_middle::mir::mono::CodegenUnit;
-use rustc_middle::ty::layout::{HasParamEnv, LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, 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;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_target::abi::{
+    call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
+};
 use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
 use smallvec::SmallVec;
 
@@ -835,6 +840,12 @@ fn tcx(&self) -> TyCtxt<'tcx> {
     }
 }
 
+impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        ty::ParamEnv::reveal_all()
+    }
+}
+
 impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
     type LayoutOfResult = TyAndLayout<'tcx>;
 
@@ -848,8 +859,39 @@ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) ->
     }
 }
 
-impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        ty::ParamEnv::reveal_all()
+impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> {
+    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+            self.sess().span_fatal(span, &err.to_string())
+        } else {
+            match fn_abi_request {
+                FnAbiRequest::OfFnPtr { sig, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+                        sig,
+                        extra_args,
+                        err
+                    );
+                }
+                FnAbiRequest::OfInstance { instance, extra_args } => {
+                    span_bug!(
+                        span,
+                        "`fn_abi_of_instance({}, {:?})` failed: {}",
+                        instance,
+                        extra_args,
+                        err
+                    );
+                }
+            }
+        }
     }
 }
index 019bf4a09a7870000ef18d685fa297c39642e595..093aceda2b7413ef4713a220598e7415bf6f6562 100644 (file)
@@ -1,6 +1,6 @@
 use crate::llvm;
 
-use crate::abi::{Abi, FnAbi};
+use crate::abi::Abi;
 use crate::builder::Builder;
 use crate::common::CodegenCx;
 
@@ -20,7 +20,7 @@
     CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, Op,
 };
 use rustc_middle::ty;
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::Instance;
 
@@ -200,8 +200,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
 
     let llfn = cx.declare_fn(
         &tcx.symbol_name(instance).name,
-        &FnAbi::of_fn_ptr(
-            cx,
+        &cx.fn_abi_of_fn_ptr(
             ty::Binder::dummy(tcx.mk_fn_sig(
                 iter::once(tcx.mk_unit()),
                 tcx.mk_unit(),
@@ -209,7 +208,7 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx
                 hir::Unsafety::Unsafe,
                 Abi::Rust,
             )),
-            &[],
+            ty::List::empty(),
         ),
     );
 
index c2725b83f50d62f32a6d9f1180da76e25fc010cc..1612922d43953359453b4596f168ea99c809ff7b 100644 (file)
@@ -3,12 +3,11 @@
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
 use rustc_codegen_ssa::traits::*;
 
-use crate::abi::FnAbi;
 use crate::common::CodegenCx;
 use crate::llvm;
 use crate::llvm::debuginfo::{DILocation, DIScope};
 use rustc_middle::mir::{Body, SourceScope};
-use rustc_middle::ty::layout::FnAbiExt;
+use rustc_middle::ty::layout::FnAbiOf;
 use rustc_middle::ty::{self, Instance};
 use rustc_session::config::DebugInfo;
 
@@ -94,7 +93,7 @@ fn make_mir_scope(
                 ty::ParamEnv::reveal_all(),
                 callee,
             );
-            let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
+            let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
             cx.dbg_scope_fn(callee, &callee_fn_abi, None)
         }
         None => unsafe {
index 9a6391443dd010a2c383ceaf3479eb477c02ad8b..9272435a330a5f00dca8d749988a64faaaf90496 100644 (file)
@@ -34,7 +34,7 @@
 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::symbol::Symbol;
 use rustc_span::FileNameDisplayPreference;
 use rustc_span::{self, SourceFile, SourceFileHash, Span};
 use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
@@ -89,8 +89,54 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
 
-#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
-pub struct UniqueTypeId(Symbol);
+mod unique_type_id {
+    use super::*;
+    use rustc_arena::DroplessArena;
+
+    #[derive(Copy, Hash, Eq, PartialEq, Clone)]
+    pub(super) struct UniqueTypeId(u32);
+
+    // The `&'static str`s in this type actually point into the arena.
+    //
+    // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
+    // found that to regress performance up to 2% in some cases. This might be
+    // revisited after further improvements to `indexmap`.
+    #[derive(Default)]
+    pub(super) struct TypeIdInterner {
+        arena: DroplessArena,
+        names: FxHashMap<&'static str, UniqueTypeId>,
+        strings: Vec<&'static str>,
+    }
+
+    impl TypeIdInterner {
+        #[inline]
+        pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId {
+            if let Some(&name) = self.names.get(string) {
+                return name;
+            }
+
+            let name = UniqueTypeId(self.strings.len() as u32);
+
+            // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
+            // UTF-8.
+            let string: &str =
+                unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
+            // It is safe to extend the arena allocation to `'static` because we only access
+            // these while the arena is still alive.
+            let string: &'static str = unsafe { &*(string as *const str) };
+            self.strings.push(string);
+            self.names.insert(string, name);
+            name
+        }
+
+        // Get the symbol as a string. `Symbol::as_str()` should be used in
+        // preference to this function.
+        pub(super) fn get(&self, symbol: UniqueTypeId) -> &str {
+            self.strings[symbol.0 as usize]
+        }
+    }
+}
+use unique_type_id::*;
 
 /// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
 /// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
@@ -99,7 +145,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[derive(Default)]
 pub struct TypeMap<'ll, 'tcx> {
     /// The `UniqueTypeId`s created so far.
-    unique_id_interner: Interner,
+    unique_id_interner: TypeIdInterner,
     /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
     unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
     /// A map from types to debuginfo metadata. This is an N:1 mapping.
@@ -166,8 +212,7 @@ fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'
     /// Gets the string representation of a `UniqueTypeId`. This method will fail if
     /// the ID is unknown.
     fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
-        let UniqueTypeId(interner_key) = unique_type_id;
-        self.unique_id_interner.get(interner_key)
+        self.unique_id_interner.get(unique_type_id)
     }
 
     /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
@@ -197,9 +242,9 @@ fn get_unique_type_id_of_type<'a>(
         let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
 
         let key = self.unique_id_interner.intern(&unique_type_id);
-        self.type_to_unique_id.insert(type_, UniqueTypeId(key));
+        self.type_to_unique_id.insert(type_, key);
 
-        UniqueTypeId(key)
+        key
     }
 
     /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
@@ -215,7 +260,7 @@ fn get_unique_type_id_of_enum_variant<'a>(
         let enum_variant_type_id =
             format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
         let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
-        UniqueTypeId(interner_key)
+        interner_key
     }
 
     /// Gets the unique type ID string for an enum variant part.
@@ -1656,7 +1701,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDes
             Variants::Multiple {
                 tag_encoding:
                     TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
-                ref tag,
+                tag,
                 ref variants,
                 tag_field,
             } => {
@@ -2082,10 +2127,8 @@ fn prepare_enum_metadata(
 
     let layout = cx.layout_of(enum_type);
 
-    if let (
-        &Abi::Scalar(_),
-        &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
-    ) = (&layout.abi, &layout.variants)
+    if let (Abi::Scalar(_), Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. }) =
+        (layout.abi, &layout.variants)
     {
         return FinalMetadata(discriminant_type_metadata(tag.value));
     }
@@ -2093,8 +2136,8 @@ fn prepare_enum_metadata(
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
             Variants::Single { .. } => None,
-            Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. }
-            | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
+            Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. }
+            | Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
                 Some(discriminant_type_metadata(tag.value))
             }
         };
@@ -2146,9 +2189,7 @@ fn prepare_enum_metadata(
         // A single-variant enum has no discriminant.
         Variants::Single { .. } => None,
 
-        Variants::Multiple {
-            tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
-        } => {
+        Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, tag_field, .. } => {
             // Find the integer type of the correct size.
             let size = tag.value.size(cx);
             let align = tag.value.align(cx);
@@ -2179,7 +2220,7 @@ fn prepare_enum_metadata(
             }
         }
 
-        Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
+        Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, tag_field, .. } => {
             let discr_type = tag.value.to_ty(cx.tcx);
             let (size, align) = cx.size_and_align_of(discr_type);
 
index 1aa52d975e9a015854dedef358b1c9e67955661f..37b3279fb80966dd3058b49c412e31fe70e9b087 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
 use rustc_middle::ty::{self, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
@@ -133,7 +133,7 @@ fn codegen_intrinsic_call(
             }
             sym::va_arg => {
                 match fn_abi.ret.layout.abi {
-                    abi::Abi::Scalar(ref scalar) => {
+                    abi::Abi::Scalar(scalar) => {
                         match scalar.value {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
@@ -737,7 +737,7 @@ fn gen_fn<'ll, 'tcx>(
     rust_fn_sig: ty::PolyFnSig<'tcx>,
     codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>),
 ) -> (&'ll Type, &'ll Value) {
-    let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]);
+    let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
     let llty = fn_abi.llvm_type(cx);
     let llfn = cx.declare_fn(name, &fn_abi);
     cx.set_frame_pointer_type(llfn);
@@ -918,12 +918,29 @@ macro_rules! require_simd {
     }
 
     if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
-        let n: u64 = stripped.parse().unwrap_or_else(|_| {
-            span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
-        });
+        // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
+        // If there is no suffix, use the index array length.
+        let n: u64 = if stripped.is_empty() {
+            // Make sure this is actually an array, since typeck only checks the length-suffixed
+            // version of this intrinsic.
+            match args[2].layout.ty.kind() {
+                ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
+                    len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| {
+                        span_bug!(span, "could not evaluate shuffle index array length")
+                    })
+                }
+                _ => return_error!(
+                    "simd_shuffle index must be an array of `u32`, got `{}`",
+                    args[2].layout.ty
+                ),
+            }
+        } else {
+            stripped.parse().unwrap_or_else(|_| {
+                span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
+            })
+        };
 
         require_simd!(ret_ty, "return");
-
         let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
         require!(
             out_len == n,
index 3b64ec1a99122c389952e810f7c6a3f0bdf9f219..f9172e437733f816a1084e9c7b68dbed136793f0 100644 (file)
@@ -166,25 +166,32 @@ pub fn time_trace_profiler_finish(file_name: &str) {
 // Though note that Rust can also be build with an external precompiled version of LLVM
 // which might lead to failures if the oldest tested / supported LLVM version
 // doesn't yet support the relevant intrinsics
-pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
+pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
     let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
     match (arch, s) {
-        ("x86", "pclmulqdq") => "pclmul",
-        ("x86", "rdrand") => "rdrnd",
-        ("x86", "bmi1") => "bmi",
-        ("x86", "cmpxchg16b") => "cx16",
-        ("x86", "avx512vaes") => "vaes",
-        ("x86", "avx512gfni") => "gfni",
-        ("x86", "avx512vpclmulqdq") => "vpclmulqdq",
-        ("aarch64", "fp") => "fp-armv8",
-        ("aarch64", "fp16") => "fullfp16",
-        ("aarch64", "fhm") => "fp16fml",
-        ("aarch64", "rcpc2") => "rcpc-immo",
-        ("aarch64", "dpb") => "ccpp",
-        ("aarch64", "dpb2") => "ccdp",
-        ("aarch64", "frintts") => "fptoint",
-        ("aarch64", "fcma") => "complxnum",
-        (_, s) => s,
+        ("x86", "sse4.2") => {
+            if get_version() >= (14, 0, 0) {
+                vec!["sse4.2", "crc32"]
+            } else {
+                vec!["sse4.2"]
+            }
+        }
+        ("x86", "pclmulqdq") => vec!["pclmul"],
+        ("x86", "rdrand") => vec!["rdrnd"],
+        ("x86", "bmi1") => vec!["bmi"],
+        ("x86", "cmpxchg16b") => vec!["cx16"],
+        ("x86", "avx512vaes") => vec!["vaes"],
+        ("x86", "avx512gfni") => vec!["gfni"],
+        ("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"],
+        ("aarch64", "fp") => vec!["fp-armv8"],
+        ("aarch64", "fp16") => vec!["fullfp16"],
+        ("aarch64", "fhm") => vec!["fp16fml"],
+        ("aarch64", "rcpc2") => vec!["rcpc-immo"],
+        ("aarch64", "dpb") => vec!["ccpp"],
+        ("aarch64", "dpb2") => vec!["ccdp"],
+        ("aarch64", "frintts") => vec!["fptoint"],
+        ("aarch64", "fcma") => vec!["complxnum"],
+        (_, s) => vec![s],
     }
 }
 
@@ -198,9 +205,13 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
             },
         )
         .filter(|feature| {
-            let llvm_feature = to_llvm_feature(sess, feature);
-            let cstr = CString::new(llvm_feature).unwrap();
-            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
+            for llvm_feature in to_llvm_feature(sess, feature) {
+                let cstr = CString::new(llvm_feature).unwrap();
+                if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
+                    return true;
+                }
+            }
+            false
         })
         .map(|feature| Symbol::intern(feature))
         .collect()
@@ -253,12 +264,19 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
     let mut rustc_target_features = supported_target_features(sess)
         .iter()
         .filter_map(|(feature, _gate)| {
-            let llvm_feature = to_llvm_feature(sess, *feature);
-            // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
-            target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| {
-                let (_f, desc) = target_features.remove(index);
-                (*feature, desc)
-            })
+            for llvm_feature in to_llvm_feature(sess, *feature) {
+                // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+                match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map(
+                    |index| {
+                        let (_f, desc) = target_features.remove(index);
+                        (*feature, desc)
+                    },
+                ) {
+                    Some(v) => return Some(v),
+                    None => {}
+                }
+            }
+            None
         })
         .collect::<Vec<_>>();
     rustc_target_features.extend_from_slice(&[(
@@ -373,30 +391,30 @@ pub fn llvm_global_features(sess: &Session) -> Vec<String> {
 
     let filter = |s: &str| {
         if s.is_empty() {
-            return None;
+            return vec![];
         }
         let feature = if s.starts_with('+') || s.starts_with('-') {
             &s[1..]
         } else {
-            return Some(s.to_string());
+            return vec![s.to_string()];
         };
         // Rustc-specific feature requests like `+crt-static` or `-crt-static`
         // are not passed down to LLVM.
         if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
-            return None;
+            return vec![];
         }
         // ... otherwise though we run through `to_llvm_feature` feature when
         // passing requests down to LLVM. This means that all in-language
         // features also work on the command line instead of having two
         // different names when the LLVM name and the Rust name differ.
-        Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
+        to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect()
     };
 
     // Features implied by an implicit or explicit `--target`.
-    features.extend(sess.target.features.split(',').filter_map(&filter));
+    features.extend(sess.target.features.split(',').flat_map(&filter));
 
     // -Ctarget-features
-    features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
+    features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
 
     features
 }
index 8ba3e870fbb71ca231968d12fbae82e27c91ff68..34982f769d03a5cef6dda69a6116e751a8b6cb0e 100644 (file)
@@ -1,4 +1,3 @@
-use crate::abi::FnAbi;
 use crate::attributes;
 use crate::base;
 use crate::context::CodegenCx;
@@ -8,7 +7,7 @@
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 pub use rustc_middle::mir::mono::MonoItem;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
 use rustc_middle::ty::{self, Instance, TypeFoldable};
 use rustc_session::config::CrateType;
 use rustc_target::spec::RelocModel;
@@ -53,7 +52,7 @@ fn predefine_fn(
     ) {
         assert!(!instance.substs.needs_infer());
 
-        let fn_abi = FnAbi::of_instance(self, instance, &[]);
+        let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
         let lldecl = self.declare_fn(symbol_name, &fn_abi);
         unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
         let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
index d615d230ea0d19a45dc5fca07233cc39cbb67526..757ccbddbeedf140c425a1eaee7608f048fcbd77 100644 (file)
@@ -1,10 +1,9 @@
-use crate::abi::FnAbi;
 use crate::common::*;
 use crate::context::TypeLowering;
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{FnAbiExt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, 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};
@@ -23,7 +22,7 @@ fn uncached_llvm_type<'a, 'tcx>(
 ) -> &'a Type {
     match layout.abi {
         Abi::Scalar(_) => bug!("handled elsewhere"),
-        Abi::Vector { ref element, count } => {
+        Abi::Vector { element, count } => {
             let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
             return cx.type_vector(element, count);
         }
@@ -177,7 +176,7 @@ pub trait LayoutLlvmExt<'tcx> {
     fn scalar_llvm_type_at<'a>(
         &self,
         cx: &CodegenCx<'a, 'tcx>,
-        scalar: &Scalar,
+        scalar: Scalar,
         offset: Size,
     ) -> &'a Type;
     fn scalar_pair_element_llvm_type<'a>(
@@ -218,7 +217,7 @@ fn is_llvm_scalar_pair(&self) -> bool {
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
     fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let Abi::Scalar(scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
             if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
@@ -231,7 +230,9 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
                 ty::Adt(def, _) if def.is_box() => {
                     cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
                 }
-                ty::FnPtr(sig) => cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[])),
+                ty::FnPtr(sig) => {
+                    cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
+                }
                 _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO),
             };
             cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
@@ -286,7 +287,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
     }
 
     fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let Abi::Scalar(scalar) = self.abi {
             if scalar.is_bool() {
                 return cx.type_i1();
             }
@@ -297,7 +298,7 @@ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
     fn scalar_llvm_type_at<'a>(
         &self,
         cx: &CodegenCx<'a, 'tcx>,
-        scalar: &Scalar,
+        scalar: Scalar,
         offset: Size,
     ) -> &'a Type {
         match scalar.value {
@@ -337,7 +338,7 @@ fn scalar_pair_element_llvm_type<'a>(
         }
 
         let (a, b) = match self.abi {
-            Abi::ScalarPair(ref a, ref b) => (a, b),
+            Abi::ScalarPair(a, b) => (a, b),
             _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
         };
         let scalar = [a, b][index];
index 1446624b8815743269f2124ff20e6ce4ebf8b125..0713e167c53b8b73a7962f0bd2100e13c60444c3 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_codegen_ssa"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 test = false
index 4fb51ecc1d347db0789d6e6de2fd03f73f6b6e8e..826c09cd948f649e0edf10d9cf26b6e835b06ae9 100644 (file)
@@ -637,7 +637,7 @@ fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) {
     cmd.arg("-o");
     cmd.arg(&dwp_out_filename);
 
-    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+    let mut new_path = sess.get_tools_search_paths(false);
     if let Some(path) = env::var_os("PATH") {
         new_path.extend(env::split_paths(&path));
     }
@@ -2555,8 +2555,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
             match ld_impl {
                 LdImpl::Lld => {
                     if sess.target.lld_flavor == LldFlavor::Ld64 {
-                        let tools_path =
-                            sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+                        let tools_path = sess.get_tools_search_paths(false);
                         let ld64_exe = tools_path
                             .into_iter()
                             .map(|p| p.join("gcc-ld"))
@@ -2571,8 +2570,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
                             arg
                         });
                     } else {
-                        let tools_path =
-                            sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
+                        let tools_path = sess.get_tools_search_paths(false);
                         let lld_path = tools_path
                             .into_iter()
                             .map(|p| p.join("gcc-ld"))
index 9e1c6a169f1525235ac04d526f6a54dd944cd6b4..e3b0eea0d89c70ac0dd0988731bc6352852efa72 100644 (file)
@@ -15,7 +15,6 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::{json, Encoder};
 use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
-use rustc_session::search_paths::PathKind;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
@@ -101,7 +100,7 @@ pub fn get_linker<'a>(
 
     // The compiler's sysroot often has some bundled tools, so add it to the
     // PATH for the child.
-    let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
+    let mut new_path = sess.get_tools_search_paths(self_contained);
     let mut msvc_changed_path = false;
     if sess.target.is_like_msvc {
         if let Some(ref tool) = msvc_tool {
index f0b32c96309d629f90e66a6aaa94c71967404753..e842f5e9391c806b0ba62d6b98b3ab4d4cd2c299 100644 (file)
@@ -404,7 +404,7 @@ fn msvc_enum_fallback(
 
             // calculate the range of values for the dataful variant
             let dataful_discriminant_range =
-                &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
+                dataful_variant_layout.largest_niche.unwrap().scalar.valid_range;
 
             let min = dataful_discriminant_range.start;
             let min = tag.value.size(&tcx).truncate(min);
index 2ca7e8fd7e8e377e05a8a89a52a6c276137625ed..4be050fb88c2da7c936792c2ff280c951cba0329 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, LayoutOf};
+use rustc_middle::ty::layout::{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};
+use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -124,7 +124,7 @@ fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
         fx: &mut FunctionCx<'a, 'tcx, Bx>,
         bx: &mut Bx,
-        fn_abi: FnAbi<'tcx, Ty<'tcx>>,
+        fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
         fn_ptr: Bx::Value,
         llargs: &[Bx::Value],
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
@@ -337,7 +337,7 @@ fn codegen_drop_terminator(
                     def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
                     substs: drop_fn.substs,
                 };
-                let fn_abi = FnAbi::of_instance(&bx, virtual_drop, &[]);
+                let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
                 let vtable = args[1];
                 args = &args[..1];
                 (
@@ -346,7 +346,7 @@ fn codegen_drop_terminator(
                     fn_abi,
                 )
             }
-            _ => (bx.get_fn_addr(drop_fn), FnAbi::of_instance(&bx, drop_fn, &[])),
+            _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
         };
         helper.do_call(
             self,
@@ -433,7 +433,7 @@ fn codegen_assert_terminator(
         // Obtain the panic entry point.
         let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item);
         let instance = ty::Instance::mono(bx.tcx(), def_id);
-        let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
+        let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
         let llfn = bx.get_fn_addr(instance);
 
         // Codegen the actual panic invoke/call.
@@ -494,7 +494,7 @@ enum AssertIntrinsic {
                 let def_id =
                     common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
                 let instance = ty::Instance::mono(bx.tcx(), def_id);
-                let fn_abi = FnAbi::of_instance(bx, instance, &[]);
+                let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
                 let llfn = bx.get_fn_addr(instance);
 
                 // Codegen the actual panic invoke/call.
@@ -570,17 +570,14 @@ fn codegen_call_terminator(
         };
 
         let extra_args = &args[sig.inputs().skip_binder().len()..];
-        let extra_args = extra_args
-            .iter()
-            .map(|op_arg| {
-                let op_ty = op_arg.ty(self.mir, bx.tcx());
-                self.monomorphize(op_ty)
-            })
-            .collect::<Vec<_>>();
+        let extra_args = bx.tcx().mk_type_list(extra_args.iter().map(|op_arg| {
+            let op_ty = op_arg.ty(self.mir, bx.tcx());
+            self.monomorphize(op_ty)
+        }));
 
         let fn_abi = match instance {
-            Some(instance) => FnAbi::of_instance(&bx, instance, &extra_args),
-            None => FnAbi::of_fn_ptr(&bx, sig, &extra_args),
+            Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
+            None => bx.fn_abi_of_fn_ptr(sig, extra_args),
         };
 
         if intrinsic == Some(sym::transmute) {
@@ -665,8 +662,12 @@ fn codegen_call_terminator(
                         if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
                             if let mir::Operand::Constant(constant) = arg {
                                 let c = self.eval_mir_constant(constant);
-                                let (llval, ty) =
-                                    self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c);
+                                let (llval, ty) = self.simd_shuffle_indices(
+                                    &bx,
+                                    constant.span,
+                                    self.monomorphize(constant.ty()),
+                                    c,
+                                );
                                 return OperandRef {
                                     val: Immediate(llval),
                                     layout: bx.layout_of(ty),
@@ -1102,9 +1103,9 @@ fn codegen_argument(
                 // the load would just produce `OperandValue::Ref` instead
                 // of the `OperandValue::Immediate` we need for the call.
                 llval = bx.load(bx.backend_type(arg.layout), llval, align);
-                if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+                if let abi::Abi::Scalar(scalar) = arg.layout.abi {
                     if scalar.is_bool() {
-                        bx.range_metadata(llval, 0..2);
+                        bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
                     }
                 }
                 // We store bools as `i8` so we need to truncate to `i1`.
@@ -1424,7 +1425,7 @@ fn codegen_transmute_into(
         let src = self.codegen_operand(bx, src);
 
         // Special-case transmutes between scalars as simple bitcasts.
-        match (&src.layout.abi, &dst.layout.abi) {
+        match (src.layout.abi, dst.layout.abi) {
             (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
                 // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
                 if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) {
index fa8a53e60b169d96c4d25288556fbf29b15844ca..93b39dc8e9ee102c8015ca4b21ebfd9f5c5d5fd1 100644 (file)
@@ -68,7 +68,7 @@ pub fn simd_shuffle_indices(
                         if let Some(prim) = field.val.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
                             let scalar = match layout.abi {
-                                Abi::Scalar(ref x) => x,
+                                Abi::Scalar(x) => x,
                                 _ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
                             };
                             bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
index c139f915e6cbb21932924f897e7a2822da161658..c710fcc2c1dcb665e131a2bd147c2fbced879c61 100644 (file)
@@ -3,9 +3,11 @@
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
+use rustc_target::abi::Abi;
 use rustc_target::abi::Size;
 
 use super::operand::{OperandRef, OperandValue};
@@ -368,21 +370,14 @@ pub fn compute_per_local_var_debug_info(
                         {
                             let arg_index = place.local.index() - 1;
                             if target_is_msvc {
-                                // Rust compiler decomposes every &str or slice argument into two components:
-                                // a pointer to the memory address where the data is stored and a usize representing
-                                // the length of the str (or slice). These components will later be used to reconstruct
-                                // the original argument inside the body of the function that owns it (see the
-                                // definition of debug_introduce_local for more details).
-                                //
-                                // Since the original argument is declared inside a function rather than being passed
-                                // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
-                                // its data correctly. (See issue #81894 for an in-depth description of the problem).
-                                match *var_ty.kind() {
-                                    ty::Ref(_, inner_type, _) => match *inner_type.kind() {
-                                        ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
-                                        _ => VariableKind::ArgumentVariable(arg_index + 1),
-                                    },
-                                    _ => VariableKind::ArgumentVariable(arg_index + 1),
+                                // ScalarPair parameters are spilled to the stack so they need to
+                                // be marked as a `LocalVariable` for MSVC debuggers to visualize
+                                // their data correctly. (See #81894 & #88625)
+                                let var_ty_layout = self.cx.layout_of(var_ty);
+                                if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
+                                    VariableKind::LocalVariable
+                                } else {
+                                    VariableKind::ArgumentVariable(arg_index + 1)
                                 }
                             } else {
                                 // FIXME(eddyb) shouldn't `ArgumentVariable` indices be
index 75999225c031d2a071b7416a6c79d90f26e1f632..f943157dc66fa200cd61315d87754c5e2a96b501 100644 (file)
@@ -104,7 +104,6 @@ pub fn codegen_intrinsic_call(
                 }
             }
             sym::pref_align_of
-            | sym::min_align_of
             | sym::needs_drop
             | sym::type_id
             | sym::type_name
index e2edd448267175974d734b913086e88f43ebac16..37f5de309baffe7bff940fc45faaf93bb6adf534 100644 (file)
@@ -2,7 +2,7 @@
 use rustc_errors::ErrorReported;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_target::abi::call::{FnAbi, PassMode};
 
@@ -29,7 +29,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
 
     cx: &'a Bx::CodegenCx,
 
-    fn_abi: FnAbi<'tcx, Ty<'tcx>>,
+    fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
 
     /// When unwinding is initiated, we have to store this personality
     /// value somewhere so that we can load it and re-use it in the
@@ -129,6 +129,7 @@ fn new_operand<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
 
 ///////////////////////////////////////////////////////////////////////////
 
+#[instrument(level = "debug", skip(cx))]
 pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     cx: &'a Bx::CodegenCx,
     instance: Instance<'tcx>,
@@ -139,7 +140,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     let mir = cx.tcx().instance_mir(instance.def);
 
-    let fn_abi = FnAbi::of_instance(cx, instance, &[]);
+    let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
     debug!("fn_abi: {:?}", fn_abi);
 
     let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
@@ -152,20 +153,11 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     }
 
     let cleanup_kinds = analyze::cleanup_kinds(&mir);
-    // Allocate a `Block` for every basic block, except
-    // the start block, if nothing loops back to it.
-    let reentrant_start_block = !mir.predecessors()[mir::START_BLOCK].is_empty();
-    let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> =
-        mir.basic_blocks()
-            .indices()
-            .map(|bb| {
-                if bb == mir::START_BLOCK && !reentrant_start_block {
-                    Some(start_llbb)
-                } else {
-                    None
-                }
-            })
-            .collect();
+    let cached_llbbs: IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>> = mir
+        .basic_blocks()
+        .indices()
+        .map(|bb| if bb == mir::START_BLOCK { Some(start_llbb) } else { None })
+        .collect();
 
     let mut fx = FunctionCx {
         instance,
@@ -247,11 +239,6 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // Apply debuginfo to the newly allocated locals.
     fx.debug_introduce_locals(&mut bx);
 
-    // Branch to the START block, if it's not the entry block.
-    if reentrant_start_block {
-        bx.br(fx.llbb(mir::START_BLOCK));
-    }
-
     // Codegen the body of each block using reverse postorder
     // FIXME(eddyb) reuse RPO iterator between `analysis` and this.
     for (bb, _) in traversal::reverse_postorder(&mir) {
index 5cee25b5cca3b5f9fa5362341f4617aaa21f15b5..ce6cec67ad41ef7b17f7f73bf31925d3671c6c2b 100644 (file)
@@ -79,7 +79,7 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         let val = match val {
             ConstValue::Scalar(x) => {
                 let scalar = match layout.abi {
-                    Abi::Scalar(ref x) => x,
+                    Abi::Scalar(x) => x,
                     _ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
                 };
                 let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout));
@@ -87,7 +87,7 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
             }
             ConstValue::Slice { data, start, end } => {
                 let a_scalar = match layout.abi {
-                    Abi::ScalarPair(ref a, _) => a,
+                    Abi::ScalarPair(a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
                 };
                 let a = Scalar::from_pointer(
@@ -162,7 +162,7 @@ pub fn from_immediate_or_packed_pair<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         llval: V,
         layout: TyAndLayout<'tcx>,
     ) -> Self {
-        let val = if let Abi::ScalarPair(ref a, ref b) = layout.abi {
+        let val = if let Abi::ScalarPair(a, b) = layout.abi {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout);
 
             // Deconstruct the immediate aggregate.
@@ -185,7 +185,7 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         let field = self.layout.field(bx.cx(), i);
         let offset = self.layout.fields.offset(i);
 
-        let mut val = match (self.val, &self.layout.abi) {
+        let mut val = match (self.val, self.layout.abi) {
             // If the field is ZST, it has no data.
             _ if field.is_zst() => {
                 return OperandRef::new_zst(bx, field);
@@ -200,7 +200,7 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
             }
 
             // Extract a scalar component from a pair.
-            (OperandValue::Pair(a_llval, b_llval), &Abi::ScalarPair(ref a, ref b)) => {
+            (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => {
                 if offset.bytes() == 0 {
                     assert_eq!(field.size, a.value.size(bx.cx()));
                     OperandValue::Immediate(a_llval)
@@ -212,14 +212,14 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
             }
 
             // `#[repr(simd)]` types are also immediate.
-            (OperandValue::Immediate(llval), &Abi::Vector { .. }) => {
+            (OperandValue::Immediate(llval), Abi::Vector { .. }) => {
                 OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
             }
 
             _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
         };
 
-        match (&mut val, &field.abi) {
+        match (&mut val, field.abi) {
             (OperandValue::Immediate(llval), _) => {
                 // Bools in union fields needs to be truncated.
                 *llval = bx.to_immediate(*llval, field);
@@ -308,7 +308,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
             }
             OperandValue::Pair(a, b) => {
                 let (a_scalar, b_scalar) = match dest.layout.abi {
-                    Abi::ScalarPair(ref a, ref b) => (a, b),
+                    Abi::ScalarPair(a, b) => (a, b),
                     _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout),
                 };
                 let ty = bx.backend_type(dest.layout);
index b48d6d42b43577d62242d06c0d2fc12b8d396815..4b07ed1a1e6c2b2bf884db3b94d42b206c58b9d4 100644 (file)
@@ -99,7 +99,7 @@ pub fn project_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                     // Also handles the first field of Scalar, ScalarPair, and Vector layouts.
                     self.llval
                 }
-                Abi::ScalarPair(ref a, ref b)
+                Abi::ScalarPair(a, b)
                     if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) =>
                 {
                     // Offset matches second field.
@@ -222,7 +222,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                     .map_or(index.as_u32() as u128, |discr| discr.val);
                 return bx.cx().const_uint_big(cast_to, discr_val);
             }
-            Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
             }
         };
index 3d8ea29160bd0941785274fa746c2883fb2fbae3..7403c21a9060e0e17da08a9b325d87525970cf99 100644 (file)
@@ -300,7 +300,7 @@ pub fn codegen_rvalue_operand(
                         let llval = operand.immediate();
 
                         let mut signed = false;
-                        if let Abi::Scalar(ref scalar) = operand.layout.abi {
+                        if let Abi::Scalar(scalar) = operand.layout.abi {
                             if let Int(_, s) = scalar.value {
                                 // We use `i1` for bytes that are always `0` or `1`,
                                 // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
@@ -308,8 +308,7 @@ pub fn codegen_rvalue_operand(
                                 // then `i1 1` (i.e., E::B) is effectively `i8 -1`.
                                 signed = !scalar.is_bool() && s;
 
-                                let er = scalar.valid_range_exclusive(bx.cx());
-                                if er.end != er.start
+                                if !scalar.is_always_valid(bx.cx())
                                     && scalar.valid_range.end >= scalar.valid_range.start
                                 {
                                     // We want `table[e as usize ± k]` to not
@@ -487,20 +486,6 @@ pub fn codegen_rvalue_operand(
                 )
             }
 
-            mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
-                let ty = self.monomorphize(ty);
-                assert!(bx.cx().type_is_sized(ty));
-                let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes());
-                let tcx = self.cx.tcx();
-                (
-                    bx,
-                    OperandRef {
-                        val: OperandValue::Immediate(val),
-                        layout: self.cx.layout_of(tcx.types.usize),
-                    },
-                )
-            }
-
             mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
                 let content_ty = self.monomorphize(content_ty);
                 let content_layout = bx.cx().layout_of(content_ty);
@@ -525,6 +510,27 @@ pub fn codegen_rvalue_operand(
                 let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
                 (bx, operand)
             }
+
+            mir::Rvalue::NullaryOp(null_op, ty) => {
+                let ty = self.monomorphize(ty);
+                assert!(bx.cx().type_is_sized(ty));
+                let layout = bx.cx().layout_of(ty);
+                let val = match null_op {
+                    mir::NullOp::SizeOf => layout.size.bytes(),
+                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::Box => unreachable!(),
+                };
+                let val = bx.cx().const_usize(val);
+                let tcx = self.cx.tcx();
+                (
+                    bx,
+                    OperandRef {
+                        val: OperandValue::Immediate(val),
+                        layout: self.cx.layout_of(tcx.types.usize),
+                    },
+                )
+            }
+
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(bx.cx().tcx().is_static(def_id));
                 let static_ = bx.get_static(def_id);
index dbb7e1ee8b17fd68e573850a13a7b427ffaf5e93..82b79fd0b2ac3e1d525d2ec622a8b8332a081639 100644 (file)
@@ -8,14 +8,15 @@
 use rustc_errors::ErrorReported;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_session::{
     config::{self, OutputFilenames, PrintRequest},
     Session,
 };
 use rustc_span::symbol::Symbol;
+use rustc_target::abi::call::FnAbi;
 use rustc_target::spec::Target;
 
 pub use rustc_data_structures::sync::MetadataRef;
@@ -38,12 +39,19 @@ pub trait BackendTypes {
 }
 
 pub trait Backend<'tcx>:
-    Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+    Sized
+    + BackendTypes
+    + HasTyCtxt<'tcx>
+    + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+    + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
 {
 }
 
 impl<'tcx, T> Backend<'tcx> for T where
-    Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+    Self: BackendTypes
+        + HasTyCtxt<'tcx>
+        + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+        + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
 {
 }
 
index afb8ee3c40d5569169327fe602c1d2bcc54c5093..e7da96f0adafdaf53b510f3084c7f4ad684b59c3 100644 (file)
 use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
-use rustc_target::abi::{Abi, Align, Scalar, Size};
+use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
 use rustc_target::spec::HasTargetSpec;
 
-use std::ops::Range;
-
 #[derive(Copy, Clone)]
 pub enum OverflowOp {
     Add,
@@ -126,13 +124,13 @@ fn checked_binop(
 
     fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
     fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
-        if let Abi::Scalar(ref scalar) = layout.abi {
+        if let Abi::Scalar(scalar) = layout.abi {
             self.to_immediate_scalar(val, scalar)
         } else {
             val
         }
     }
-    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value;
+    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
 
     fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
     fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
@@ -158,7 +156,7 @@ fn write_operand_repeatedly(
         dest: PlaceRef<'tcx, Self::Value>,
     ) -> Self;
 
-    fn range_metadata(&mut self, load: Self::Value, range: Range<u128>);
+    fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
     fn nonnull_metadata(&mut self, load: Self::Value);
 
     fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
index 20f6618712327870212d734e8ca15062b03aacbf..5260b7cc33120e0e36c05d3d79eb0ad537b7d317 100644 (file)
@@ -28,7 +28,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
 
     fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
 
-    fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value;
+    fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
     fn from_const_alloc(
         &self,
         layout: TyAndLayout<'tcx>,
index 1653d5cf6c560ae42e05550cf2a72f1491ca366d..a51273732ae6f8b335c4dfb137770dfdfd6f1232 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_const_eval"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 171fc45ea4696c4ed5b414ff68b3ba15fba522e9..57af0ff07143373cacfd7f11d2423e7e0bc8cd7c 100644 (file)
@@ -51,10 +51,11 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     assert!(!layout.is_unsized());
     let ret = ecx.allocate(layout, MemoryKind::Stack)?;
 
-    let name =
-        with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id())));
-    let prom = cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p));
-    trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom);
+    trace!(
+        "eval_body_using_ecx: pushing stack frame for global: {}{}",
+        with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))),
+        cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p))
+    );
 
     ecx.push_stack_frame(
         cid.instance,
index 40419a4d201ac0b198ab799ebf509a020ea23b7e..10afd9560fa956da688e68238a35b12d5c9a435e 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -34,8 +34,14 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
 }
 
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
-    let parent_id = tcx.hir().get_parent_did(hir_id);
-    if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false }
+    let parent_id = tcx.hir().get_parent_node(hir_id);
+    matches!(
+        tcx.hir().get(parent_id),
+        hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
+            ..
+        })
+    )
 }
 
 /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
@@ -70,19 +76,6 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     }
 }
 
-/// Checks whether the given item is an `impl` that has a `const` modifier.
-fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let node = tcx.hir().get(hir_id);
-    matches!(
-        node,
-        hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
-            ..
-        })
-    )
-}
-
 fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     is_const_fn(tcx, def_id)
         && match tcx.lookup_const_stability(def_id) {
@@ -103,10 +96,5 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 }
 
 pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        is_const_fn_raw,
-        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
-        is_promotable_const_fn,
-        ..*providers
-    };
+    *providers = Providers { is_const_fn_raw, is_promotable_const_fn, ..*providers };
 }
index 8a90686b9003f5c391cd1e7a077969ab1a12a42c..ae20f6f97b2124ad6099d4c5a1b2a114ab3e26fc 100644 (file)
@@ -36,12 +36,17 @@ fn hook_panic_fn(
         let def_id = instance.def_id();
         if Some(def_id) == self.tcx.lang_items().panic_fn()
             || Some(def_id) == self.tcx.lang_items().panic_str()
+            || Some(def_id) == self.tcx.lang_items().panic_display()
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
-            // &str
+            // &str or &&str
             assert!(args.len() == 1);
 
-            let msg_place = self.deref_operand(&args[0])?;
+            let mut msg_place = self.deref_operand(&args[0])?;
+            while msg_place.layout.ty.is_ref() {
+                msg_place = self.deref_operand(&msg_place.into())?;
+            }
+
             let msg = Symbol::intern(self.read_str(&msg_place)?);
             let span = self.find_closest_untracked_caller_location();
             let (file, line, col) = self.location_triple_for_span(span);
index 07e974b72664bbefc7103a91f80532ea3135ec6e..698742fe98ceb0e5868c2510b9cb9f4c6a955630 100644 (file)
@@ -62,15 +62,10 @@ fn numeric_intrinsic<Tag>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<T
             ensure_monomorphic_enough(tcx, tp_ty)?;
             ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
         }
-        sym::min_align_of | sym::pref_align_of => {
+        sym::pref_align_of => {
             // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
             let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
-            let n = match name {
-                sym::pref_align_of => layout.align.pref.bytes(),
-                sym::min_align_of => layout.align.abi.bytes(),
-                _ => bug!(),
-            };
-            ConstValue::from_machine_usize(n, &tcx)
+            ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx)
         }
         sym::type_id => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -160,17 +155,14 @@ pub fn emulate_intrinsic(
                 self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
             }
 
-            sym::min_align_of
-            | sym::pref_align_of
+            sym::pref_align_of
             | sym::needs_drop
             | sym::type_id
             | sym::type_name
             | sym::variant_count => {
                 let gid = GlobalId { instance, promoted: None };
                 let ty = match intrinsic_name {
-                    sym::min_align_of | sym::pref_align_of | sym::variant_count => {
-                        self.tcx.types.usize
-                    }
+                    sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
                     sym::needs_drop => self.tcx.types.bool,
                     sym::type_id => self.tcx.types.u64,
                     sym::type_name => self.tcx.mk_static_str(),
@@ -194,7 +186,7 @@ pub fn emulate_intrinsic(
                 let val = self.read_scalar(&args[0])?.check_init()?;
                 let bits = val.to_bits(layout_of.size)?;
                 let kind = match layout_of.abi {
-                    Abi::Scalar(ref scalar) => scalar.value,
+                    Abi::Scalar(scalar) => scalar.value,
                     _ => span_bug!(
                         self.cur_span(),
                         "{} called on invalid type {:?}",
@@ -234,7 +226,8 @@ pub fn emulate_intrinsic(
                     &r,
                 )?;
                 let val = if overflowed {
-                    let num_bits = l.layout.size.bits();
+                    let size = l.layout.size;
+                    let num_bits = size.bits();
                     if l.layout.abi.is_signed() {
                         // For signed ints the saturated value depends on the sign of the first
                         // term since the sign of the second term can be inferred from this and
@@ -259,10 +252,7 @@ pub fn emulate_intrinsic(
                         // unsigned
                         if is_add {
                             // max unsigned
-                            Scalar::from_uint(
-                                u128::MAX >> (128 - num_bits),
-                                Size::from_bits(num_bits),
-                            )
+                            Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
                         } else {
                             // underflow to 0
                             Scalar::from_uint(0u128, Size::from_bits(num_bits))
index 63aca67c9443c13b1724fa6fb2087cc6e94ec327..de870bd5c6cf1be3972ad5eede57b696572a7501 100644 (file)
@@ -274,11 +274,11 @@ fn try_read_immediate_from_mplace(
                 let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?;
                 Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout }))
             }
-            Abi::ScalarPair(ref a, ref b) => {
+            Abi::ScalarPair(a, b) => {
                 // We checked `ptr_align` above, so all fields will have the alignment they need.
                 // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
-                let (a, b) = (&a.value, &b.value);
+                let (a, b) = (a.value, b.value);
                 let (a_size, b_size) = (a.size(self), b.size(self));
                 let b_offset = a_size.align_to(b.align(self).abi);
                 assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
@@ -648,7 +648,7 @@ pub fn read_discriminant(
                 };
                 return Ok((discr, index));
             }
-            Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
             }
         };
index 95a44e3fecf3d19b249c1f81924f123b5ebc010b..0da6d8169bd3a7b36c25f7d9aca0d7fbb1b3f871 100644 (file)
@@ -752,7 +752,7 @@ fn write_immediate_to_mplace_no_validate(
                 // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
                 let (a, b) = match dest.layout.abi {
-                    Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
+                    Abi::ScalarPair(a, b) => (a.value, b.value),
                     _ => span_bug!(
                         self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
@@ -1000,7 +1000,7 @@ pub fn write_discriminant(
             }
             Variants::Multiple {
                 tag_encoding: TagEncoding::Direct,
-                tag: ref tag_layout,
+                tag: tag_layout,
                 tag_field,
                 ..
             } => {
@@ -1022,7 +1022,7 @@ pub fn write_discriminant(
             Variants::Multiple {
                 tag_encoding:
                     TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
-                tag: ref tag_layout,
+                tag: tag_layout,
                 tag_field,
                 ..
             } => {
index 09bd07660a33eb0fa3ca56cc16ce2d62c6ce7b37..6e35b33188cd238b858d1f3e696cebe86f49f364 100644 (file)
@@ -270,18 +270,23 @@ pub fn eval_rvalue_into_place(
                 M::box_alloc(self, &dest)?;
             }
 
-            NullaryOp(mir::NullOp::SizeOf, ty) => {
+            NullaryOp(null_op, ty) => {
                 let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                 let layout = self.layout_of(ty)?;
                 if layout.is_unsized() {
                     // FIXME: This should be a span_bug (#80742)
                     self.tcx.sess.delay_span_bug(
                         self.frame().current_span(),
-                        &format!("SizeOf nullary MIR operator called for unsized type {}", ty),
+                        &format!("Nullary MIR operator called for unsized type {}", ty),
                     );
                     throw_inval!(SizeOfUnsizedType(ty));
                 }
-                self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?;
+                let val = match null_op {
+                    mir::NullOp::SizeOf => layout.size.bytes(),
+                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::Box => unreachable!(),
+                };
+                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
             }
 
             Cast(cast_kind, ref operand, cast_ty) => {
index 1c8e5e9e23c3caefab88cd27f834bd67c5b8db48..a06903aedf6499a167e499e27cf7502f42958e3a 100644 (file)
@@ -187,17 +187,14 @@ fn check_argument_compat(
             return false;
         }
         // Compare layout
-        match (&caller.abi, &callee.abi) {
+        match (caller.abi, callee.abi) {
             // Different valid ranges are okay (once we enforce validity,
             // that will take care to make it UB to leave the range, just
             // like for transmute).
-            (abi::Abi::Scalar(ref caller), abi::Abi::Scalar(ref callee)) => {
-                caller.value == callee.value
+            (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value,
+            (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => {
+                caller1.value == callee1.value && caller2.value == callee2.value
             }
-            (
-                abi::Abi::ScalarPair(ref caller1, ref caller2),
-                abi::Abi::ScalarPair(ref callee1, ref callee2),
-            ) => caller1.value == callee1.value && caller2.value == callee2.value,
             // Be conservative
             _ => false,
         }
index 03e0a8e7901d94c86f2077dd026e207e1aaea148..fc69770bf6a306f68bd89aa3f2ff60005507b4e2 100644 (file)
@@ -77,7 +77,7 @@ macro_rules! throw_validation_failure {
 ///
 macro_rules! try_validation {
     ($e:expr, $where:expr,
-    $( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
+    $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
     ) => {{
         match $e {
             Ok(x) => x,
@@ -618,40 +618,38 @@ fn try_visit_primitive(
     fn visit_scalar(
         &mut self,
         op: &OpTy<'tcx, M::PointerTag>,
-        scalar_layout: &ScalarAbi,
+        scalar_layout: ScalarAbi,
     ) -> InterpResult<'tcx> {
-        let value = self.read_scalar(op)?;
-        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());
-        assert!(hi <= max_hi);
-        // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128`
-        if (lo == 0 && hi == max_hi) || (hi + 1 == lo) {
+        if scalar_layout.valid_range.is_full_for(op.layout.size) {
             // Nothing to check
             return Ok(());
         }
-        // At least one value is excluded. Get the bits.
+        // At least one value is excluded.
+        let valid_range = scalar_layout.valid_range;
+        let WrappingRange { start, end } = valid_range;
+        let max_value = op.layout.size.unsigned_int_max();
+        assert!(end <= max_value);
+        // Determine the allowed range
+        let value = self.read_scalar(op)?;
         let value = try_validation!(
             value.check_init(),
             self.path,
             err_ub!(InvalidUninitBytes(None)) => { "{}", value }
-                expected { "something {}", wrapping_range_format(valid_range, max_hi) },
+                expected { "something {}", wrapping_range_format(valid_range, max_value) },
         );
         let bits = match value.try_to_int() {
             Err(_) => {
                 // So this is a pointer then, and casting to an int failed.
                 // Can only happen during CTFE.
                 let ptr = self.ecx.scalar_to_ptr(value);
-                if lo == 1 && hi == max_hi {
+                if start == 1 && end == max_value {
                     // Only null is the niche.  So make sure the ptr is NOT null.
                     if self.ecx.memory.ptr_may_be_null(ptr) {
                         throw_validation_failure!(self.path,
                             { "a potentially null pointer" }
                             expected {
                                 "something that cannot possibly fail to be {}",
-                                wrapping_range_format(valid_range, max_hi)
+                                wrapping_range_format(valid_range, max_value)
                             }
                         )
                     }
@@ -663,7 +661,7 @@ fn visit_scalar(
                         { "a pointer" }
                         expected {
                             "something that cannot possibly fail to be {}",
-                            wrapping_range_format(valid_range, max_hi)
+                            wrapping_range_format(valid_range, max_value)
                         }
                     )
                 }
@@ -676,7 +674,7 @@ fn visit_scalar(
         } else {
             throw_validation_failure!(self.path,
                 { "{}", bits }
-                expected { "something {}", wrapping_range_format(valid_range, max_hi) }
+                expected { "something {}", wrapping_range_format(valid_range, max_value) }
             )
         }
     }
@@ -786,7 +784,7 @@ fn visit_value(&mut self, op: &OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx>
                     { "a value of uninhabited type {:?}", op.layout.ty }
                 );
             }
-            Abi::Scalar(ref scalar_layout) => {
+            Abi::Scalar(scalar_layout) => {
                 self.visit_scalar(op, scalar_layout)?;
             }
             Abi::ScalarPair { .. } | Abi::Vector { .. } => {
index d02b4286c175a6396771cdc31e4f7ecebd0c822f..9eec930f59e525cf5212e02cbadbf2226cd2bcb2 100644 (file)
@@ -22,7 +22,7 @@
 use std::ops::Deref;
 
 use super::ops::{self, NonConstOp, Status};
-use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
+use super::qualifs::{self, CustomEq, HasMutInterior, NeedsNonConstDrop};
 use super::resolver::FlowSensitiveAnalysis;
 use super::{is_lang_panic_fn, ConstCx, Qualif};
 use crate::const_eval::is_unstable_const_fn;
@@ -39,7 +39,7 @@
 #[derive(Default)]
 pub struct Qualifs<'mir, 'tcx> {
     has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
-    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
+    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
     indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
 }
 
@@ -80,14 +80,14 @@ pub fn needs_drop(
         location: Location,
     ) -> bool {
         let ty = ccx.body.local_decls[local].ty;
-        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
+        if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) {
             return false;
         }
 
         let needs_drop = self.needs_drop.get_or_insert_with(|| {
             let ConstCx { tcx, body, .. } = *ccx;
 
-            FlowSensitiveAnalysis::new(NeedsDrop, ccx)
+            FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
                 .into_engine(tcx, &body)
                 .iterate_to_fixpoint()
                 .into_results_cursor(&body)
@@ -384,11 +384,11 @@ fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
                         match pred.skip_binder() {
                             ty::ExistentialPredicate::AutoTrait(_)
                             | ty::ExistentialPredicate::Projection(_) => {
-                                self.check_op(ops::ty::TraitBound(kind))
+                                self.check_op(ops::ty::DynTrait(kind))
                             }
                             ty::ExistentialPredicate::Trait(trait_ref) => {
                                 if Some(trait_ref.def_id) != self.tcx.lang_items().sized_trait() {
-                                    self.check_op(ops::ty::TraitBound(kind))
+                                    self.check_op(ops::ty::DynTrait(kind))
                                 }
                             }
                         }
@@ -648,7 +648,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                 }
             }
 
-            Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
             Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
 
             Rvalue::UnaryOp(_, ref operand) => {
@@ -888,6 +888,10 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                 if is_lang_panic_fn(tcx, callee) {
                     self.check_op(ops::Panic);
 
+                    // `begin_panic` and `panic_display` are generic functions that accept
+                    // types other than str. Check to enforce that only str can be used in
+                    // const-eval.
+
                     // const-eval of the `begin_panic` fn assumes the argument is `&str`
                     if Some(callee) == tcx.lang_items().begin_panic_fn() {
                         match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
@@ -896,6 +900,15 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
                         }
                     }
 
+                    // const-eval of the `panic_display` fn assumes the argument is `&&str`
+                    if Some(callee) == tcx.lang_items().panic_display() {
+                        match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
+                            ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
+                                {}
+                            _ => self.check_op(ops::PanicNonStr),
+                        }
+                    }
+
                     return;
                 }
 
@@ -988,12 +1001,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location
 
                 let mut err_span = self.span;
 
-                // Check to see if the type of this place can ever have a drop impl. If not, this
-                // `Drop` terminator is frivolous.
-                let ty_needs_drop =
-                    dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env);
+                let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
+                    self.ccx,
+                    dropped_place.ty(self.body, self.tcx).ty,
+                );
 
-                if !ty_needs_drop {
+                if !ty_needs_non_const_drop {
                     return;
                 }
 
index a5cb0f4e14b178547dc1c1f6ae305f748b3d8183..d1fd3ceaa589a4e112d672cfbe3dea0ec4042ceb 100644 (file)
@@ -79,6 +79,7 @@ pub fn is_lang_panic_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
     // Keep in sync with what that function handles!
     Some(def_id) == tcx.lang_items().panic_fn()
         || Some(def_id) == tcx.lang_items().panic_str()
+        || Some(def_id) == tcx.lang_items().panic_display()
         || Some(def_id) == tcx.lang_items().begin_panic_fn()
         || Some(def_id) == tcx.lang_items().panic_fmt()
         || Some(def_id) == tcx.lang_items().begin_panic_fmt()
index 8923d989b2944a63796842d5e1f6cbddf2e60e26..1d0ee949a221b8df1ff9fe29abfb079d6fb066e0 100644 (file)
@@ -599,12 +599,60 @@ fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
         }
 
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-            feature_err(
+            let mut err = feature_err(
                 &ccx.tcx.sess.parse_sess,
                 sym::const_fn_trait_bound,
                 span,
                 "trait bounds other than `Sized` on const fn parameters are unstable",
-            )
+            );
+
+            match ccx.fn_sig() {
+                Some(fn_sig) if !fn_sig.span.contains(span) => {
+                    err.span_label(fn_sig.span, "function declared as const here");
+                }
+                _ => {}
+            }
+
+            err
+        }
+    }
+
+    #[derive(Debug)]
+    pub struct DynTrait(pub mir::LocalKind);
+    impl NonConstOp for DynTrait {
+        fn importance(&self) -> DiagnosticImportance {
+            match self.0 {
+                mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
+                mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
+                    DiagnosticImportance::Primary
+                }
+            }
+        }
+
+        fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
+            if ccx.const_kind() != hir::ConstContext::ConstFn {
+                Status::Allowed
+            } else {
+                Status::Unstable(sym::const_fn_trait_bound)
+            }
+        }
+
+        fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+            let mut err = feature_err(
+                &ccx.tcx.sess.parse_sess,
+                sym::const_fn_trait_bound,
+                span,
+                "trait objects in const fn are unstable",
+            );
+
+            match ccx.fn_sig() {
+                Some(fn_sig) if !fn_sig.span.contains(span) => {
+                    err.span_label(fn_sig.span, "function declared as const here");
+                }
+                _ => {}
+            }
+
+            err
         }
     }
 
index b08ce219034ce09eb5b38d2b4dd7fcea7b7b5959..f2ba5a1ebb19be757884b27d555268116199e560 100644 (file)
@@ -5,7 +5,7 @@
 
 use super::check::Qualifs;
 use super::ops::{self, NonConstOp};
-use super::qualifs::{NeedsDrop, Qualif};
+use super::qualifs::{NeedsNonConstDrop, Qualif};
 use super::ConstCx;
 
 /// Returns `true` if we should use the more precise live drop checker that runs after drop
@@ -78,10 +78,10 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc
         match &terminator.kind {
             mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                 let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
-                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
-                    bug!(
-                        "Drop elaboration left behind a Drop for a type that does not need dropping"
-                    );
+                if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
+                    // Instead of throwing a bug, we just return here. This is because we have to
+                    // run custom `const Drop` impls.
+                    return;
                 }
 
                 if dropped_place.is_indirect() {
index 413a9638eb37b172717d4473f48079215170cf72..cb9b4bcb77a8574ea8baa50bd54b1c3e95587de1 100644 (file)
@@ -3,10 +3,14 @@
 //! See the `Qualif` trait for more info.
 
 use rustc_errors::ErrorReported;
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{
+    self, ImplSource, Obligation, ObligationCause, SelectionContext,
+};
 
 use super::ConstCx;
 
@@ -17,7 +21,7 @@ pub fn in_any_value_of_ty(
 ) -> ConstQualifs {
     ConstQualifs {
         has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
-        needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
+        needs_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
         custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
         error_occured,
     }
@@ -97,22 +101,58 @@ fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tc
 /// This must be ruled out (a) because we cannot run `Drop` during compile-time
 /// as that might not be a `const fn`, and (b) because implicit promotion would
 /// remove side-effects that occur as part of dropping that value.
-pub struct NeedsDrop;
+pub struct NeedsNonConstDrop;
 
-impl Qualif for NeedsDrop {
-    const ANALYSIS_NAME: &'static str = "flow_needs_drop";
+impl Qualif for NeedsNonConstDrop {
+    const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop";
     const IS_CLEARED_ON_MOVE: bool = true;
 
     fn in_qualifs(qualifs: &ConstQualifs) -> bool {
         qualifs.needs_drop
     }
 
-    fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(cx.tcx, cx.param_env)
+    fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool {
+        // Avoid selecting for simple cases.
+        match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() {
+            Ok([]) => return false,
+            Err(ty::util::AlwaysRequiresDrop) => return true,
+            // If we've got a single component, select with that
+            // to increase the chance that we hit the selection cache.
+            Ok([t]) => ty = t,
+            Ok([..]) => {}
+        }
+
+        let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() {
+            did
+        } else {
+            // there is no way to define a type that needs non-const drop
+            // without having the lang item present.
+            return false;
+        };
+        let trait_ref =
+            ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) };
+        let obligation = Obligation::new(
+            ObligationCause::dummy(),
+            cx.param_env,
+            ty::Binder::dummy(ty::TraitPredicate {
+                trait_ref,
+                constness: ty::BoundConstness::ConstIfConst,
+            }),
+        );
+
+        let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
+            let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
+            selcx.select(&obligation)
+        });
+        match implsrc {
+            Ok(Some(ImplSource::ConstDrop(_)))
+            | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
+            _ => true,
+        }
     }
 
     fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
-        adt.has_dtor(cx.tcx)
+        adt.has_non_const_dtor(cx.tcx)
     }
 }
 
index 6822ad2d7b5dd0d3e02f0f9a2029b407bd249839..52d04cb4ff1e0f689a6794e6d5d7631b4ece72fd 100644 (file)
@@ -231,7 +231,7 @@ fn validate_candidate(&self, candidate: Candidate) -> Result<(), Unpromotable> {
 
                         // We cannot promote things that need dropping, since the promoted value
                         // would not get dropped.
-                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
+                        if self.qualif_local::<qualifs::NeedsNonConstDrop>(place.local) {
                             return Err(Unpromotable);
                         }
 
@@ -520,6 +520,7 @@ fn validate_rvalue(&self, rvalue: &Rvalue<'tcx>) -> Result<(), Unpromotable> {
             Rvalue::NullaryOp(op, _) => match op {
                 NullOp::Box => return Err(Unpromotable),
                 NullOp::SizeOf => {}
+                NullOp::AlignOf => {}
             },
 
             Rvalue::UnaryOp(op, operand) => {
index 40a32a76c9446e49114d4794b0b7f9dfbf2f6f5b..b09b2227f3e88b63e860cef4a90da2d6ea0759dc 100644 (file)
@@ -9,7 +9,7 @@
 use rustc_middle::mir::{
     AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
     PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
-    TerminatorKind,
+    TerminatorKind, START_BLOCK,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
@@ -130,6 +130,9 @@ fn fail(&self, location: Location, msg: impl AsRef<str>) {
     }
 
     fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
+        if bb == START_BLOCK {
+            self.fail(location, "start block must not have predecessors")
+        }
         if let Some(bb) = self.body.basic_blocks().get(bb) {
             let src = self.body.basic_blocks().get(location.block).unwrap();
             match (src.is_cleanup, bb.is_cleanup, edge_kind) {
index bc13ca26e2e22059d24130eb298a38f2b8d409c5..49962570129704a91392ec7117e379e53d0aa040 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_data_structures"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 09b91083a6347c61238198d399491ffec892891c..a9db3497b23908a50548e9a24ab74f189feed37d 100644 (file)
@@ -83,8 +83,58 @@ impl<G> DepthFirstSearch<'graph, G>
 where
     G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
 {
-    pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
-        Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
+    pub fn new(graph: &'graph G) -> Self {
+        Self { graph, stack: vec![], visited: BitSet::new_empty(graph.num_nodes()) }
+    }
+
+    /// Version of `push_start_node` that is convenient for chained
+    /// use.
+    pub fn with_start_node(mut self, start_node: G::Node) -> Self {
+        self.push_start_node(start_node);
+        self
+    }
+
+    /// Pushes another start node onto the stack. If the node
+    /// has not already been visited, then you will be able to
+    /// walk its successors (and so forth) after the current
+    /// contents of the stack are drained. If multiple start nodes
+    /// are added into the walk, then their mutual successors
+    /// will all be walked. You can use this method once the
+    /// iterator has been completely drained to add additional
+    /// start nodes.
+    pub fn push_start_node(&mut self, start_node: G::Node) {
+        if self.visited.insert(start_node) {
+            self.stack.push(start_node);
+        }
+    }
+
+    /// Searches all nodes reachable from the current start nodes.
+    /// This is equivalent to just invoke `next` repeatedly until
+    /// you get a `None` result.
+    pub fn complete_search(&mut self) {
+        while let Some(_) = self.next() {}
+    }
+
+    /// Returns true if node has been visited thus far.
+    /// A node is considered "visited" once it is pushed
+    /// onto the internal stack; it may not yet have been yielded
+    /// from the iterator. This method is best used after
+    /// the iterator is completely drained.
+    pub fn visited(&self, node: G::Node) -> bool {
+        self.visited.contains(node)
+    }
+}
+
+impl<G> std::fmt::Debug for DepthFirstSearch<'_, G>
+where
+    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut f = fmt.debug_set();
+        for n in self.visited.iter() {
+            f.entry(&n);
+        }
+        f.finish()
     }
 }
 
index 0e038e88b221dfed3f8d3b6aabbdb0b272d9ab96..c498c289337f1a1eebe77955943ab88812ae2b9c 100644 (file)
@@ -20,3 +20,19 @@ fn is_cyclic() {
     assert!(!is_cyclic(&diamond_acyclic));
     assert!(is_cyclic(&diamond_cyclic));
 }
+
+#[test]
+fn dfs() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+
+    let result: Vec<usize> = DepthFirstSearch::new(&graph).with_start_node(0).collect();
+    assert_eq!(result, vec![0, 2, 3, 1]);
+}
+
+#[test]
+fn dfs_debug() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+    let mut dfs = DepthFirstSearch::new(&graph).with_start_node(0);
+    dfs.complete_search();
+    assert_eq!(format!("{{0, 1, 2, 3}}"), format!("{:?}", dfs));
+}
index dff22855629a8e4b9f93f6b7e7041a56b415ba2b..3560df6e5e204548dc2966179e26052d90298bfb 100644 (file)
@@ -32,7 +32,7 @@ fn depth_first_search(&self, from: Self::Node) -> iterate::DepthFirstSearch<'_,
     where
         Self: WithNumNodes,
     {
-        iterate::DepthFirstSearch::new(selffrom)
+        iterate::DepthFirstSearch::new(self).with_start_node(from)
     }
 }
 
index d128a688e751f72e75bc3767dc5bd6e34d7bdf7a..b1f04bfbf0a848993e327fd4a7c07ce037422f5f 100644 (file)
@@ -18,9 +18,9 @@
 #![feature(extend_one)]
 #![feature(hash_raw_entry)]
 #![feature(in_band_lifetimes)]
-#![feature(iter_map_while)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
+#![feature(never_type)]
 #![feature(type_alias_impl_trait)]
 #![feature(new_uninit)]
 #![feature(nll)]
index 14db71cb8f0701040da9ad286fa75c2ed6580f75..417c61242a539d584e1aac62e7bad937b379b321 100644 (file)
@@ -1,6 +1,5 @@
 use crate::fx::{FxHashMap, FxHasher};
 use crate::sync::{Lock, LockGuard};
-use smallvec::SmallVec;
 use std::borrow::Borrow;
 use std::collections::hash_map::RawEntryMut;
 use std::hash::{Hash, Hasher};
@@ -37,24 +36,7 @@ fn default() -> Self {
 impl<T> Sharded<T> {
     #[inline]
     pub fn new(mut value: impl FnMut() -> T) -> Self {
-        // Create a vector of the values we want
-        let mut values: SmallVec<[_; SHARDS]> =
-            (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect();
-
-        // Create an uninitialized array
-        let mut shards: mem::MaybeUninit<[CacheAligned<Lock<T>>; SHARDS]> =
-            mem::MaybeUninit::uninit();
-
-        unsafe {
-            // Copy the values into our array
-            let first = shards.as_mut_ptr() as *mut CacheAligned<Lock<T>>;
-            values.as_ptr().copy_to_nonoverlapping(first, SHARDS);
-
-            // Ignore the content of the vector
-            values.set_len(0);
-
-            Sharded { shards: shards.assume_init() }
-        }
+        Sharded { shards: [(); SHARDS].map(|()| CacheAligned(Lock::new(value()))) }
     }
 
     /// The shard is selected by hashing `val` with `FxHasher`.
index 18b352cf3b0b9152f42eb6c43dfd536c92f4e1dd..354f9dd93cc4d4e491f6a15feffcdbf491a837dd 100644 (file)
@@ -209,6 +209,12 @@ fn hash_stable(&self, _: &mut CTX, hasher: &mut $crate::stable_hasher::StableHas
 impl_stable_hash_via_hash!(char);
 impl_stable_hash_via_hash!(());
 
+impl<CTX> HashStable<CTX> for ! {
+    fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
+        unreachable!()
+    }
+}
+
 impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         self.get().hash_stable(ctx, hasher)
index ba8616cc6ef73cb9340001bd3e99d1385c9e566c..6721e00027d42383889284dc3898a919827e2a06 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_driver"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 crate-type = ["dylib"]
index 53053327d0dab276b0c90134b18854a84d0fe483..4c6a2baaef1e512972460433edf13ae172d8b5fd 100644 (file)
@@ -677,10 +677,7 @@ fn print_crate_info(
                     println!("{}", targets.join("\n"));
                 }
                 Sysroot => println!("{}", sess.sysroot.display()),
-                TargetLibdir => println!(
-                    "{}",
-                    sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display()
-                ),
+                TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
                 TargetSpec => println!("{}", sess.target.to_json().pretty()),
                 FileNames | CrateName => {
                     let input = input.unwrap_or_else(|| {
index 270e5301895a44852cbfd652d63849324e504529..7d5f3e4672a0fe57bf28d2c2210579b4d29232ca 100644 (file)
@@ -1,4 +1,4 @@
 [package]
 name = "rustc_error_codes"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
index bc2c03a0220826f81558b003a18cbd71a891f04e..a6d6d19762b58dde38260fbbfd5842a6a95d012c 100644 (file)
@@ -15,13 +15,13 @@ form of initializer was used.
 For example, the code above can be fixed to:
 
 ```
-enum Foo {
-    FirstValue(i32)
-}
+type U32 = u32;
+let t: U32 = 4;
+```
 
-fn main() {
-    let u = Foo::FirstValue(0i32);
+or:
 
-    let t = 4;
-}
+```
+struct U32 { value: u32 }
+let t = U32 { value: 4 };
 ```
index 3e663df866caaac49ba8e63468672409c5430359..24268aef2222a8b51a0093b36abc97c73951faad 100644 (file)
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 The length of the platform-intrinsic function `simd_shuffle` wasn't specified.
 
 Erroneous code example:
 
-```compile_fail,E0439
+```ignore (no longer emitted)
 #![feature(platform_intrinsics)]
 
 extern "platform-intrinsic" {
index c74fd60e530c1f037de179c82c4d5ccca648f893..4846dc43605f8f0f07be62f63f3afbb7030c7f52 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_errors"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 550c1c43530df6090c08f33d5f711f213e641c21..41a73268f467345df99ff6b6e57fb967fd2aada6 100644 (file)
@@ -74,6 +74,10 @@ pub fn normal<S: Into<String>>(t: S) -> DiagnosticStyledString {
     pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
         DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
     }
+
+    pub fn content(&self) -> String {
+        self.0.iter().map(|x| x.content()).collect::<String>()
+    }
 }
 
 #[derive(Debug, PartialEq, Eq)]
@@ -82,6 +86,14 @@ pub enum StringPart {
     Highlighted(String),
 }
 
+impl StringPart {
+    pub fn content(&self) -> &str {
+        match self {
+            &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
+        }
+    }
+}
+
 impl Diagnostic {
     pub fn new(level: Level, message: &str) -> Self {
         Diagnostic::new_with_code(level, None, message)
@@ -304,6 +316,21 @@ pub fn multipart_suggestion(
         )
     }
 
+    /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic.
+    /// In other words, multiple changes need to be applied as part of this suggestion.
+    pub fn multipart_suggestion_verbose(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        self.multipart_suggestion_with_style(
+            msg,
+            suggestion,
+            applicability,
+            SuggestionStyle::ShowAlways,
+        )
+    }
     /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
     pub fn multipart_suggestion_with_style(
         &mut self,
index c498ce7dbe426aaed3a4396265d9fa61cd3255b5..6f84b0d400e5d44c062b49f7fb8c9bcaa0bd28fa 100644 (file)
@@ -258,6 +258,20 @@ pub fn multipart_suggestion(
         self
     }
 
+    /// See [`Diagnostic::multipart_suggestion()`].
+    pub fn multipart_suggestion_verbose(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.0.allow_suggestions {
+            return self;
+        }
+        self.0.diagnostic.multipart_suggestion_verbose(msg, suggestion, applicability);
+        self
+    }
+
     /// See [`Diagnostic::tool_only_multipart_suggestion()`].
     pub fn tool_only_multipart_suggestion(
         &mut self,
index b1526cf78d2e9c9d504e2235ec80241c5dfe6891..03e8534ef289f6c6c6b303c9283ddaed8bdde120 100644 (file)
@@ -1028,15 +1028,13 @@ fn print_error_count(&mut self, registry: &Registry) {
             let mut error_codes = self
                 .emitted_diagnostic_codes
                 .iter()
-                .filter_map(|x| {
-                    match &x {
+                .filter_map(|x| match &x {
                     DiagnosticId::Error(s)
-                        if let Ok(Some(_explanation)) = registry.try_find_description(s) =>
+                        if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
                     {
                         Some(s.clone())
                     }
                     _ => None,
-                }
                 })
                 .collect::<Vec<_>>();
             if !error_codes.is_empty() {
index 1be9321e4fed5a551d98938b5803e74f1be3df29..45237ab2e9f2502b32f48afd13dbf582c9e7c7a7 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_expand"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 build = false
 
 [lib]
index 35df8aae4babb99d5488b87b99234a5d4ce6d7d1..b630bc1f4732f57f1185233d405e73d9b71518ff 100644 (file)
 use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
-use rustc_errors::{DiagnosticBuilder, ErrorReported};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
-use rustc_span::def_id::{CrateNum, DefId};
+use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::source_map::SourceMap;
@@ -843,6 +843,7 @@ pub fn expn_data(
 
 pub trait ResolverExpand {
     fn next_node_id(&mut self) -> NodeId;
+    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
 
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(
@@ -1136,13 +1137,15 @@ pub fn resolve_path(
 }
 
 /// Extracts a string literal from the macro expanded version of `expr`,
-/// emitting `err_msg` if `expr` is not a string literal. This does not stop
-/// compilation on error, merely emits a non-fatal error and returns `None`.
+/// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
+/// The returned bool indicates whether an applicable suggestion has already been
+/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
+/// indicates that an ast error was encountered.
 pub fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
     err_msg: &str,
-) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> {
+) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> {
     // Perform eager expansion on the expression.
     // We want to be able to handle e.g., `concat!("foo", "bar")`.
     let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
@@ -1150,14 +1153,27 @@ pub fn expr_to_spanned_string<'a>(
     Err(match expr.kind {
         ast::ExprKind::Lit(ref l) => match l.kind {
             ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
+            ast::LitKind::ByteStr(_) => {
+                let mut err = cx.struct_span_err(l.span, err_msg);
+                err.span_suggestion(
+                    expr.span.shrink_to_lo(),
+                    "consider removing the leading `b`",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+                Some((err, true))
+            }
             ast::LitKind::Err(_) => None,
-            _ => Some(cx.struct_span_err(l.span, err_msg)),
+            _ => Some((cx.struct_span_err(l.span, err_msg), false)),
         },
         ast::ExprKind::Err => None,
-        _ => Some(cx.struct_span_err(expr.span, err_msg)),
+        _ => Some((cx.struct_span_err(expr.span, err_msg), false)),
     })
 }
 
+/// Extracts a string literal from the macro expanded version of `expr`,
+/// emitting `err_msg` if `expr` is not a string literal. This does not stop
+/// compilation on error, merely emits a non-fatal error and returns `None`.
 pub fn expr_to_string(
     cx: &mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
@@ -1165,7 +1181,7 @@ pub fn expr_to_string(
 ) -> Option<(Symbol, ast::StrStyle)> {
     expr_to_spanned_string(cx, expr, err_msg)
         .map_err(|err| {
-            err.map(|mut err| {
+            err.map(|(mut err, _)| {
                 err.emit();
             })
         })
index 3ccf9f446a63efa3b556902307568db60fad73e7..d32593f34adefc750c68f8a9ed4f1b20f5f8a29c 100644 (file)
@@ -588,7 +588,7 @@ fn collect_invocations(
         // Resolve `$crate`s in the fragment for pretty-printing.
         self.cx.resolver.resolve_dollar_crates();
 
-        let invocations = {
+        let mut invocations = {
             let mut collector = InvocationCollector {
                 // Non-derive macro invocations cannot see the results of cfg expansion - they
                 // will either be removed along with the item, or invoked before the cfg/cfg_attr
@@ -613,6 +613,19 @@ fn collect_invocations(
             self.cx
                 .resolver
                 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
+
+            if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
+                for (invoc, _) in invocations.iter_mut() {
+                    let expn_id = invoc.expansion_data.id;
+                    let parent_def = self.cx.resolver.invocation_parent(expn_id);
+                    let span = match &mut invoc.kind {
+                        InvocationKind::Bang { ref mut span, .. } => span,
+                        InvocationKind::Attr { attr, .. } => &mut attr.span,
+                        InvocationKind::Derive { path, .. } => &mut path.span,
+                    };
+                    *span = span.with_parent(Some(parent_def));
+                }
+            }
         }
 
         (fragment, invocations)
@@ -1373,14 +1386,17 @@ fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
         // `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` lint if needed.
         // See #78991 for an investigation of treating macros in this position
         // as statements, rather than expressions, during parsing.
-        if let StmtKind::Expr(expr) = &stmt.kind {
-            if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) {
+        let res = match &stmt.kind {
+            StmtKind::Expr(expr)
+                if matches!(**expr, ast::Expr { kind: ast::ExprKind::MacCall(..), .. }) =>
+            {
                 self.cx.current_expansion.is_trailing_mac = true;
+                // Don't use `assign_id` for this statement - it may get removed
+                // entirely due to a `#[cfg]` on the contained expression
+                noop_flat_map_stmt(stmt, self)
             }
-        }
-
-        let res = assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self));
-
+            _ => assign_id!(self, &mut stmt.id, || noop_flat_map_stmt(stmt, self)),
+        };
         self.cx.current_expansion.is_trailing_mac = false;
         res
     }
index fb7479eafc86f5e155640393e1efd8891f4c5873..363cc72b52c3e5bc46483c5b94f796bde701144f 100644 (file)
@@ -72,7 +72,7 @@ pub(super) fn parse(
                                             // this with just `span.edition()`. A
                                             // `SyntaxContext::root()` from the current crate will
                                             // have the edition of the current crate, and a
-                                            // `SyntaxxContext::root()` from a foreign crate will
+                                            // `SyntaxContext::root()` from a foreign crate will
                                             // have the edition of that crate (which we manually
                                             // retrieve via the `edition` parameter).
                                             if span.ctxt() == SyntaxContext::root() {
index 55700f7b0d495e119b07b2fda73c744314082cce..52b60c3047e1c9180ac3d314b6f3b5e666f91ef8 100644 (file)
@@ -745,7 +745,7 @@ fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
         self.sess.source_map().lookup_char_pos(span.lo()).file
     }
     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
-        span.parent()
+        span.parent_callsite()
     }
     fn source(&mut self, span: Self::Span) -> Self::Span {
         span.source_callsite()
@@ -758,6 +758,12 @@ fn end(&mut self, span: Self::Span) -> LineColumn {
         let loc = self.sess.source_map().lookup_char_pos(span.hi());
         LineColumn { line: loc.line, column: loc.col.to_usize() }
     }
+    fn before(&mut self, span: Self::Span) -> Self::Span {
+        span.shrink_to_lo()
+    }
+    fn after(&mut self, span: Self::Span) -> Self::Span {
+        span.shrink_to_hi()
+    }
     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
         let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
         let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
index ee381e34251b54e5bf282026e9ad0b8fb90a0618..3d8d0db20d122d8decb88ac75fa6b48a083d3c05 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_feature"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 725f8b8763af17d3d048395884ede1d07caec3c3..61e27d2e4cd41053db35dc55d60c8effeabdc63b 100644 (file)
@@ -16,7 +16,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
index a3807a2bb9fde64cb5a3a6e2574de2a9176f145f..efa93c186363a1570e100b657ecf8a8afbe3490e 100644 (file)
@@ -37,7 +37,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: $edition,
-                    description: concat!($($doc,)*),
                 }
             ),+];
 
@@ -639,9 +638,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows specifying the as-needed link modifier
     (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
 
-    /// Allows unnamed fields of struct and union type
-    (incomplete, unnamed_fields, "1.53.0", Some(49804), None),
-
     /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
     (active, more_qualified_paths, "1.54.0", Some(86935), None),
 
index e2aa54a59b2021401c8ab1f7fb751a34c50c1ac9..f74ea0e0c4d271c979df7f85c251922e1eb59f12 100644 (file)
@@ -453,6 +453,9 @@ macro_rules! experimental {
     ),
     // Enumerates "identity-like" conversion methods to suggest on type mismatch.
     rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE),
+    // Prevents field reads in the marked trait or method to be considered
+    // during dead code analysis.
+    rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Const related:
index cf102aa16e0571ffbf89dbbb64ced39c99282ebf..b25aab21e491afa1a54ac74cf7ad3fb7bff7bcc5 100644 (file)
@@ -51,7 +51,6 @@ pub struct Feature {
     pub since: &'static str,
     issue: Option<NonZeroU32>,
     pub edition: Option<Edition>,
-    description: &'static str,
 }
 
 #[derive(Copy, Clone, Debug)]
index efab0200ff502dbe26ea6c51fd9a563cc3eebe01..7b9b68268eacd8df4f5d51e684b5796f11a59e96 100644 (file)
@@ -16,7 +16,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
@@ -34,7 +33,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
index c417e978b311de92007fc70f584e8169dfe87b91..34c3fe2a005c81ae4ead69a38b967107ee8635c2 100644 (file)
@@ -1,4 +1,4 @@
 [package]
 name = "rustc_fs_util"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
index 87c41ae171ef5b361a07be97ee70353c0493ffcd..d657fdb1a778947df30d8c013138df5c075a9a87 100644 (file)
@@ -1,4 +1,4 @@
 [package]
 name = "rustc_graphviz"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
index c92551c29307b9d75b4a4e3914a921e0deadfac0..3b6e6db72d1f7128e42a099c2c2fef6001e9c5f1 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_hir"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
@@ -17,3 +17,4 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
 tracing = "0.1"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+odht = { version = "0.3.0", features = ["nightly"] }
index 3e8b98e9f5493dd146664a8f2820670e56530aaa..f07e52e04daa9d8020ee9b6ee58c2d6f72de845f 100644 (file)
@@ -28,9 +28,9 @@ macro_rules! arena_types {
             [] pat_field: rustc_hir::PatField<$tcx>,
             [] fn_decl: rustc_hir::FnDecl<$tcx>,
             [] foreign_item: rustc_hir::ForeignItem<$tcx>,
-            [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
+            [few] foreign_item_ref: rustc_hir::ForeignItemRef,
             [] impl_item: rustc_hir::ImplItem<$tcx>,
-            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+            [] impl_item_ref: rustc_hir::ImplItemRef,
             [] item: rustc_hir::Item<$tcx>,
             [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
             [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
index 853415c4173b561d26ff7e1a7cb6e9ff7d663204..cb668eb35e093da9b2194eef756f4208e436c677 100644 (file)
@@ -598,6 +598,11 @@ pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
         }
     }
 
+    #[track_caller]
+    pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {
+        self.map_id(|_| panic!("unexpected `Res::Local`"))
+    }
+
     pub fn macro_kind(self) -> Option<MacroKind> {
         match self {
             Res::Def(DefKind::Macro(kind), _) => Some(kind),
diff --git a/compiler/rustc_hir/src/def_path_hash_map.rs b/compiler/rustc_hir/src/def_path_hash_map.rs
new file mode 100644 (file)
index 0000000..8bfb47a
--- /dev/null
@@ -0,0 +1,37 @@
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_span::def_id::{DefIndex, DefPathHash};
+
+#[derive(Clone, Default)]
+pub struct Config;
+
+impl odht::Config for Config {
+    type Key = DefPathHash;
+    type Value = DefIndex;
+
+    type EncodedKey = [u8; 16];
+    type EncodedValue = [u8; 4];
+
+    type H = odht::UnHashFn;
+
+    #[inline]
+    fn encode_key(k: &DefPathHash) -> [u8; 16] {
+        k.0.to_le_bytes()
+    }
+
+    #[inline]
+    fn encode_value(v: &DefIndex) -> [u8; 4] {
+        v.as_u32().to_le_bytes()
+    }
+
+    #[inline]
+    fn decode_key(k: &[u8; 16]) -> DefPathHash {
+        DefPathHash(Fingerprint::from_le_bytes(*k))
+    }
+
+    #[inline]
+    fn decode_value(v: &[u8; 4]) -> DefIndex {
+        DefIndex::from_u32(u32::from_le_bytes(*v))
+    }
+}
+
+pub type DefPathHashMap = odht::HashTableOwned<Config>;
index 30a367052cba58411702cd20b1e0f50cbd478b9f..ca29351455e628654ae48fed1851e475f321b6cd 100644 (file)
@@ -6,14 +6,15 @@
 
 pub use crate::def_id::DefPathHash;
 use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::def_path_hash_map::DefPathHashMap;
 use crate::hir;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
-use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
 
 use std::fmt::{self, Write};
 use std::hash::Hash;
@@ -27,7 +28,7 @@
 pub struct DefPathTable {
     index_to_key: IndexVec<DefIndex, DefKey>,
     def_path_hashes: IndexVec<DefIndex, DefPathHash>,
-    def_path_hash_to_index: UnhashMap<DefPathHash, DefIndex>,
+    def_path_hash_to_index: DefPathHashMap,
 }
 
 impl DefPathTable {
@@ -43,7 +44,7 @@ fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
 
         // Check for hash collisions of DefPathHashes. These should be
         // exceedingly rare.
-        if let Some(existing) = self.def_path_hash_to_index.insert(def_path_hash, index) {
+        if let Some(existing) = self.def_path_hash_to_index.insert(&def_path_hash, &index) {
             let def_path1 = DefPath::make(LOCAL_CRATE, existing, |idx| self.def_key(idx));
             let def_path2 = DefPath::make(LOCAL_CRATE, index, |idx| self.def_key(idx));
 
@@ -86,7 +87,7 @@ pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
 
     pub fn enumerated_keys_and_path_hashes(
         &self,
-    ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ {
+    ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + ExactSizeIterator + '_ {
         self.index_to_key
             .iter_enumerated()
             .map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
@@ -107,6 +108,11 @@ pub struct Definitions {
 
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+
+    def_id_to_span: IndexVec<LocalDefId, Span>,
+
+    /// The [StableCrateId] of the local crate.
+    stable_crate_id: StableCrateId,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -324,7 +330,7 @@ pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefI
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
-    pub fn new(stable_crate_id: StableCrateId) -> Definitions {
+    pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -341,11 +347,19 @@ pub fn new(stable_crate_id: StableCrateId) -> Definitions {
         let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
         assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
 
+        let mut def_id_to_span = IndexVec::new();
+        // A relative span's parent must be an absolute span.
+        debug_assert_eq!(crate_span.data_untracked().parent, None);
+        let _root = def_id_to_span.push(crate_span);
+        debug_assert_eq!(_root, root);
+
         Definitions {
             table,
             def_id_to_hir_id: Default::default(),
             hir_id_to_def_id: Default::default(),
             expansions_that_defined: Default::default(),
+            def_id_to_span,
+            stable_crate_id,
         }
     }
 
@@ -361,6 +375,7 @@ pub fn create_def(
         data: DefPathData,
         expn_id: ExpnId,
         mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32,
+        span: Span,
     ) -> LocalDefId {
         debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id);
 
@@ -385,6 +400,11 @@ pub fn create_def(
             self.expansions_that_defined.insert(def_id, expn_id);
         }
 
+        // A relative span's parent must be an absolute span.
+        debug_assert_eq!(span.data_untracked().parent, None);
+        let _id = self.def_id_to_span.push(span);
+        debug_assert_eq!(_id, def_id);
+
         def_id
     }
 
@@ -412,16 +432,28 @@ pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId {
         self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
     }
 
+    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
+    #[inline]
+    pub fn def_span(&self, def_id: LocalDefId) -> Span {
+        self.def_id_to_span[def_id]
+    }
+
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
         self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
     }
 
     #[inline(always)]
-    pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
+    pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> LocalDefId {
+        debug_assert!(hash.stable_crate_id() == self.stable_crate_id);
         self.table
             .def_path_hash_to_index
             .get(&hash)
-            .map(|&local_def_index| LocalDefId { local_def_index })
+            .map(|local_def_index| LocalDefId { local_def_index })
+            .unwrap()
+    }
+
+    pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap {
+        &self.table.def_path_hash_to_index
     }
 }
 
index 84bc37170c6346d1bd819d54bacb17972cd0c900..05b652fd5af2c4245dd6d727e7b9c4ef0a941abc 100644 (file)
@@ -21,7 +21,7 @@
 use rustc_target::spec::abi::Abi;
 
 use smallvec::SmallVec;
-use std::collections::{BTreeMap, BTreeSet};
+use std::collections::BTreeMap;
 use std::fmt;
 
 #[derive(Copy, Clone, Encodable, HashStable_Generic)]
@@ -653,16 +653,6 @@ pub struct WhereEqPredicate<'hir> {
     pub rhs_ty: &'hir Ty<'hir>,
 }
 
-#[derive(Default, Encodable, Debug, HashStable_Generic)]
-pub struct ModuleItems {
-    // Use BTreeSets here so items are in the same order as in the
-    // list of all items in Crate
-    pub items: BTreeSet<ItemId>,
-    pub trait_items: BTreeSet<TraitItemId>,
-    pub impl_items: BTreeSet<ImplItemId>,
-    pub foreign_items: BTreeSet<ForeignItemId>,
-}
-
 /// The top-level data structure that stores the entire contents of
 /// the crate currently being compiled.
 ///
@@ -674,10 +664,6 @@ pub struct Crate<'hir> {
     pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
     pub bodies: BTreeMap<BodyId, Body<'hir>>,
 
-    /// 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>,
-
     /// Map indicating what traits are in scope for places where this
     /// is relevant; generated by resolve.
     pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
@@ -2759,7 +2745,7 @@ pub enum ItemKind<'hir> {
     /// A module.
     Mod(Mod<'hir>),
     /// An external module, e.g. `extern { .. }`.
-    ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
+    ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] },
     /// Module-level inline assembly (from `global_asm!`).
     GlobalAsm(&'hir InlineAsm<'hir>),
     /// A type alias, e.g., `type Foo = Bar<u8>`.
@@ -2796,7 +2782,7 @@ pub struct Impl<'hir> {
     pub of_trait: Option<TraitRef<'hir>>,
 
     pub self_ty: &'hir Ty<'hir>,
-    pub items: &'hir [ImplItemRef<'hir>],
+    pub items: &'hir [ImplItemRef],
 }
 
 impl ItemKind<'_> {
@@ -2860,13 +2846,12 @@ pub struct TraitItemRef {
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
 #[derive(Debug, HashStable_Generic)]
-pub struct ImplItemRef<'hir> {
+pub struct ImplItemRef {
     pub id: ImplItemId,
     #[stable_hasher(project(name))]
     pub ident: Ident,
     pub kind: AssocItemKind,
     pub span: Span,
-    pub vis: Visibility<'hir>,
     pub defaultness: Defaultness,
 }
 
@@ -2900,12 +2885,11 @@ pub fn hir_id(&self) -> HirId {
 /// passes to find the impl they want without loading the ID (which
 /// means fewer edges in the incremental compilation graph).
 #[derive(Debug, HashStable_Generic)]
-pub struct ForeignItemRef<'hir> {
+pub struct ForeignItemRef {
     pub id: ForeignItemId,
     #[stable_hasher(project(name))]
     pub ident: Ident,
     pub span: Span,
-    pub vis: Visibility<'hir>,
 }
 
 #[derive(Debug)]
@@ -3234,12 +3218,7 @@ pub fn hir_id(&self) -> Option<HirId> {
         }
     }
 
-    /// Returns `Constness::Const` when this node is a const fn/impl/item,
-    ///
-    /// HACK(fee1-dead): or an associated type in a trait. This works because
-    /// only typeck cares about const trait predicates, so although the predicates
-    /// query would return const predicates when it does not need to be const,
-    /// it wouldn't have any effect.
+    /// Returns `Constness::Const` when this node is a const fn/impl/item.
     pub fn constness_for_typeck(&self) -> Constness {
         match self {
             Node::Item(Item {
@@ -3258,7 +3237,6 @@ pub fn constness_for_typeck(&self) -> Constness {
 
             Node::Item(Item { kind: ItemKind::Const(..), .. })
             | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
-            | Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
 
             _ => Constness::NotConst,
index 137782a6dc78dcf809b196cd9dc0b447017d7eb4..1ac2625dd475483edce4e66030a81f5f222eb741 100644 (file)
@@ -392,10 +392,10 @@ fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
     fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
         walk_impl_item(self, ii)
     }
-    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
+    fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) {
         walk_foreign_item_ref(self, ii)
     }
-    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
+    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) {
         walk_impl_item_ref(self, ii)
     }
     fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) {
@@ -1042,22 +1042,20 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
 
 pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
     visitor: &mut V,
-    foreign_item_ref: &'v ForeignItemRef<'v>,
+    foreign_item_ref: &'v ForeignItemRef,
 ) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
+    let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
     visitor.visit_nested_foreign_item(id);
     visitor.visit_ident(ident);
-    visitor.visit_vis(vis);
 }
 
-pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
+pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) {
     // N.B., deliberately force a compilation error if/when new fields are added.
-    let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
+    let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref;
     visitor.visit_nested_impl_item(id);
     visitor.visit_ident(ident);
     visitor.visit_associated_item_kind(kind);
-    visitor.visit_vis(vis);
     visitor.visit_defaultness(defaultness);
 }
 
index b85ed0cb4bbe59ecc1b2e707342cea7aefbc4eb2..d69a247054026f9a403ecbd9851d8f0416e15fff 100644 (file)
@@ -283,6 +283,7 @@ pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Sym
     // a weak lang item, but do not have it defined.
     Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::None;
     PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
+    PanicDisplay,            sym::panic_display,       panic_display,              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;
index 42575273839a9760daca044dbb611125e1a6b3d2..ce36648d6df118b4e6238e328592b0352f13fc12 100644 (file)
@@ -16,6 +16,7 @@
 
 mod arena;
 pub mod def;
+pub mod def_path_hash_map;
 pub mod definitions;
 pub use rustc_span::def_id;
 mod hir;
index c7510b7ec1422d2e9a66d72adb87cfb124083333..46a8e7deeed047bcccd932c9f7cd501201c3c312 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_hir_pretty"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 36054c0484782016fd0bb57c1f151d383a76d610..67f92bc0a51a7b8a161f792589e49ce9227441bb 100644 (file)
@@ -1036,7 +1036,7 @@ pub fn print_stmt(&mut self, st: &hir::Stmt<'_>) {
         self.maybe_print_comment(st.span.lo());
         match st.kind {
             hir::StmtKind::Local(ref loc) => {
-                self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc));
+                self.print_local(loc.init, |this| this.print_local_decl(&loc));
             }
             hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
             hir::StmtKind::Expr(ref expr) => {
index 9156243a10c0a50d9f43354595e3fce09c0feba2..dece752c1945f693bdd40129d41b019f699ac441 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_incremental"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index e1a2b619763f23516839018d21d853319945b22e..b984a1321e0aa06e0e7e4887d899ce2a3152ef0d 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_index"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 15649bb678e244d6c227ea4e00560067457cad14..f87ea43b1a72c8720360eedbec17d6e42b5b733d 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_infer"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 32150c7f4c615dfc18f5bd70481fc7ba5ba24dbd..b8089b2499b66524bef2f6ef2da45291c4e6af9c 100644 (file)
@@ -1971,6 +1971,8 @@ pub fn report_and_explain_type_error(
         trace: TypeTrace<'tcx>,
         terr: &TypeError<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
+        use crate::traits::ObligationCauseCode::MatchExpressionArm;
+
         debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
 
         let span = trace.cause.span(self.tcx);
@@ -2013,6 +2015,19 @@ pub fn report_and_explain_type_error(
                         _ => {}
                     }
                 }
+                if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
+                    trace.cause.code
+                {
+                    if let hir::MatchSource::TryDesugar = source {
+                        if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
+                            err.note(&format!(
+                                "`?` operator cannot convert from `{}` to `{}`",
+                                found_ty.content(),
+                                expected_ty.content(),
+                            ));
+                        }
+                    }
+                }
                 err
             }
             FailureCode::Error0644(failure_str) => {
@@ -2345,7 +2360,7 @@ enum SubOrigin<'hir> {
                 );
                 err.span_suggestion(
                     generics.where_clause.tail_span_for_suggestion(),
-                    "consider adding a where clause".into(),
+                    "consider adding a where clause",
                     suggestion,
                     Applicability::MaybeIncorrect,
                 );
@@ -2585,9 +2600,7 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
             CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
                 Error0308(match source {
-                    hir::MatchSource::TryDesugar => {
-                        "try expression alternatives have incompatible types"
-                    }
+                    hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
                     _ => "`match` arms have incompatible types",
                 })
             }
index c60a7149e40eb30bb85f019df45857eff2b0f3ca..35c8786dcd3ac7b4d181c0ef8998d96406b03f78 100644 (file)
@@ -29,11 +29,17 @@ pub(super) fn try_report_mismatched_static_lifetime(&self) -> Option<ErrorReport
             SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause,
             _ => return None,
         };
-        let (parent, impl_def_id) = match &cause.code {
+        // If we added a "points at argument expression" obligation, we remove it here, we care
+        // about the original obligation only.
+        let code = match &cause.code {
+            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
+            _ => &cause.code,
+        };
+        let (parent, impl_def_id) = match code {
             ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
             _ => return None,
         };
-        let binding_span = match **parent {
+        let binding_span = match parent.code {
             ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span,
             _ => return None,
         };
index 81059fbcb10511265061f17010f237c9bdbf9229..2d47e72780ebe538cf759a48053ce88ba2ecef5b 100644 (file)
@@ -189,7 +189,7 @@ pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
         }
         if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
             let code = match &cause.code {
-                ObligationCauseCode::MatchImpl(parent, ..) => &**parent,
+                ObligationCauseCode::MatchImpl(parent, ..) => &parent.code,
                 _ => &cause.code,
             };
             if let ObligationCauseCode::ItemObligation(item_def_id) = *code {
index 61c8113d052874c0874d8cdefdead70585c1fc15..43aa8a6efcec4df5db4a056cbf43078244d0eafb 100644 (file)
@@ -2,7 +2,7 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
+use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
 use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::{MultiSpan, Span};
+use rustc_span::{MultiSpan, Span, Symbol};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
     pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
-        if let Some(ref error) = self.error {
-            debug!("try_report_impl_not_conforming_to_trait {:?}", error);
-            if let RegionResolutionError::SubSupConflict(
-                _,
-                var_origin,
-                sub_origin,
-                _sub,
-                sup_origin,
-                _sup,
-            ) = error.clone()
-            {
-                if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
-                    (&sup_origin, &sub_origin)
+        let error = self.error.as_ref()?;
+        debug!("try_report_impl_not_conforming_to_trait {:?}", error);
+        if let RegionResolutionError::SubSupConflict(
+            _,
+            var_origin,
+            sub_origin,
+            _sub,
+            sup_origin,
+            _sup,
+        ) = error.clone()
+        {
+            if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
+                if let (
+                    ValuePairs::Types(sub_expected_found),
+                    ValuePairs::Types(sup_expected_found),
+                    CompareImplMethodObligation { trait_item_def_id, .. },
+                ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
                 {
-                    if let (
-                        ValuePairs::Types(sub_expected_found),
-                        ValuePairs::Types(sup_expected_found),
-                        CompareImplMethodObligation { trait_item_def_id, .. },
-                    ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
-                    {
-                        if sup_expected_found == sub_expected_found {
-                            self.emit_err(
-                                var_origin.span(),
-                                sub_expected_found.expected,
-                                sub_expected_found.found,
-                                *trait_item_def_id,
-                            );
-                            return Some(ErrorReported);
-                        }
+                    if sup_expected_found == sub_expected_found {
+                        self.emit_err(
+                            var_origin.span(),
+                            sub_expected_found.expected,
+                            sub_expected_found.found,
+                            *trait_item_def_id,
+                        );
+                        return Some(ErrorReported);
                     }
                 }
             }
         }
+        if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
+            if let SubregionOrigin::CompareImplTypeObligation {
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } = origin
+            {
+                self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
+                return Some(ErrorReported);
+            }
+        }
         None
     }
 
@@ -107,6 +116,25 @@ fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id:
         }
         err.emit();
     }
+
+    fn emit_associated_type_err(
+        &self,
+        span: Span,
+        item_name: Symbol,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    ) {
+        let impl_sp = self.tcx().def_span(impl_item_def_id);
+        let trait_sp = self.tcx().def_span(trait_item_def_id);
+        let mut err = self
+            .tcx()
+            .sess
+            .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
+        err.span_label(impl_sp, &format!("found"));
+        err.span_label(trait_sp, &format!("expected"));
+
+        err.emit();
+    }
 }
 
 struct TypeParamSpanVisitor<'tcx> {
index 4bc59a4baf5cae5c1bddb5c0a1ffbf05d711c41f..5f99a23f86e88b1d2df0045f1f0264e585b27fe2 100644 (file)
@@ -99,6 +99,12 @@ pub(super) fn note_region_origin(
                     "...so that the definition in impl matches the definition from the trait",
                 );
             }
+            infer::CompareImplTypeObligation { span, .. } => {
+                label_or_note(
+                    span,
+                    "...so that the definition in impl matches the definition from the trait",
+                );
+            }
         }
     }
 
@@ -356,6 +362,18 @@ pub(super) fn report_concrete_failure(
                 trait_item_def_id,
                 &format!("`{}: {}`", sup, sub),
             ),
+            infer::CompareImplTypeObligation {
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => self.report_extra_impl_obligation(
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+                &format!("`{}: {}`", sup, sub),
+            ),
         }
     }
 
index bc98a3aa3f95e563d1982137b0ac0e7b4e65d71a..43d3730c04931a46aa1b28bec3b7bdcc9aa1c0fe 100644 (file)
@@ -64,6 +64,7 @@
 pub mod nll_relate;
 pub mod opaque_types;
 pub mod outlives;
+mod projection;
 pub mod region_constraints;
 pub mod resolve;
 mod sub;
@@ -427,6 +428,15 @@ pub enum SubregionOrigin<'tcx> {
         impl_item_def_id: DefId,
         trait_item_def_id: DefId,
     },
+
+    /// Comparing the signature and requirements of an impl associated type
+    /// against the containing trait
+    CompareImplTypeObligation {
+        span: Span,
+        item_name: Symbol,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    },
 }
 
 // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -1810,6 +1820,7 @@ pub fn span(&self) -> Span {
             ReferenceOutlivesReferent(_, a) => a,
             CallReturn(a) => a,
             CompareImplMethodObligation { span, .. } => span,
+            CompareImplTypeObligation { span, .. } => span,
         }
     }
 
@@ -1833,6 +1844,17 @@ pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default:
                 trait_item_def_id,
             },
 
+            traits::ObligationCauseCode::CompareImplTypeObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => SubregionOrigin::CompareImplTypeObligation {
+                span: cause.span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            },
+
             _ => default(),
         }
     }
index c211d8e94a68b1b05b2ba0f8bedb276c57d0f2ae..e88c6608aca335540020bb44f498298afd00345a 100644 (file)
@@ -519,7 +519,7 @@ fn relate_with_variance<T: Relate<'tcx>>(
 
         let old_ambient_variance = self.ambient_variance;
         self.ambient_variance = self.ambient_variance.xform(variance);
-        self.ambient_variance_info = self.ambient_variance_info.clone().xform(info);
+        self.ambient_variance_info = self.ambient_variance_info.xform(info);
 
         debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
 
@@ -597,12 +597,12 @@ fn regions(
 
         if self.ambient_covariance() {
             // Covariance: a <= b. Hence, `b: a`.
-            self.push_outlives(v_b, v_a, self.ambient_variance_info.clone());
+            self.push_outlives(v_b, v_a, self.ambient_variance_info);
         }
 
         if self.ambient_contravariance() {
             // Contravariant: b <= a. Hence, `a: b`.
-            self.push_outlives(v_a, v_b, self.ambient_variance_info.clone());
+            self.push_outlives(v_a, v_b, self.ambient_variance_info);
         }
 
         Ok(a)
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
new file mode 100644 (file)
index 0000000..9b53ab7
--- /dev/null
@@ -0,0 +1,39 @@
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::{self, ToPredicate, Ty};
+
+use crate::traits::{Obligation, PredicateObligation};
+
+use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use super::InferCtxt;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    /// Instead of normalizing an associated type projection,
+    /// this function generates an inference variable and registers
+    /// an obligation that this inference variable must be the result
+    /// of the given projection. This allows us to proceed with projections
+    /// while they cannot be resolved yet due to missing information or
+    /// simply due to the lack of access to the trait resolution machinery.
+    pub fn infer_projection(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        projection_ty: ty::ProjectionTy<'tcx>,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        obligations: &mut Vec<PredicateObligation<'tcx>>,
+    ) -> Ty<'tcx> {
+        let def_id = projection_ty.item_def_id;
+        let ty_var = self.next_ty_var(TypeVariableOrigin {
+            kind: TypeVariableOriginKind::NormalizeProjectionType,
+            span: self.tcx.def_span(def_id),
+        });
+        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
+        let obligation = Obligation::with_depth(
+            cause,
+            recursion_depth,
+            param_env,
+            projection.to_predicate(self.tcx),
+        );
+        obligations.push(obligation);
+        ty_var
+    }
+}
index d0bd508bc257f2dfd4fd63b71bdd0e65c669a7f2..9dbfa3a850ba848d505e469ac4edf8ee44f33f3b 100644 (file)
@@ -83,10 +83,6 @@ pub fn report_object_safety_error(
                     messages.push(msg.clone());
                 }
             }
-            if trait_span.is_some() {
-                // Only provide the help if its a local trait, otherwise it's not actionable.
-                violation.solution(&mut err);
-            }
         }
     }
     let has_multi_span = !multi_span.is_empty();
@@ -104,5 +100,13 @@ 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 trait_span.is_some() {
+        let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
+        reported_violations.sort();
+        for violation in reported_violations {
+            // Only provide the help if its a local trait, otherwise it's not actionable.
+            violation.solution(&mut err);
+        }
+    }
     err
 }
index b450c398946e5c66e5c2d4286c0e3121a4190d10..e1d6982f164448c1f279779e78a2dc55960917ce 100644 (file)
@@ -66,10 +66,6 @@ pub struct Obligation<'tcx, T> {
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
-    /// Diagnostics only: we opportunistically change the `code.span` when we encounter an
-    /// obligation error caused by a call argument. When this is the case, we also signal that in
-    /// this field to ensure accuracy of suggestions.
-    pub points_at_arg_span: bool,
     /// Diagnostics only: the 'root' obligation which resulted in
     /// the failure to process `obligation`. This is the obligation
     /// that was initially passed to `register_predicate_obligation`
@@ -128,7 +124,7 @@ pub fn new(
         code: FulfillmentErrorCode<'tcx>,
         root_obligation: PredicateObligation<'tcx>,
     ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation }
+        FulfillmentError { obligation, code, root_obligation }
     }
 }
 
index 33bddf1dedc1b2a6fa055207cbc5892b66e1357e..e2c13d20a9a5b5a7c11d7a0ec4b22c5e1cef1c93 100644 (file)
@@ -153,47 +153,6 @@ pub fn insert_ty(&mut self, key: ProjectionCacheKey<'tcx>, value: NormalizedTy<'
         assert!(!fresh_key, "never started projecting `{:?}`", key);
     }
 
-    /// Mark the relevant projection cache key as having its derived obligations
-    /// complete, so they won't have to be re-computed (this is OK to do in a
-    /// snapshot - if the snapshot is rolled back, the obligations will be
-    /// marked as incomplete again).
-    pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>) {
-        let mut map = self.map();
-        let ty = match map.get(&key) {
-            Some(&ProjectionCacheEntry::NormalizedTy(ref ty)) => {
-                debug!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
-                ty.value
-            }
-            ref value => {
-                // Type inference could "strand behind" old cache entries. Leave
-                // them alone for now.
-                debug!("ProjectionCacheEntry::complete({:?}) - ignoring {:?}", key, value);
-                return;
-            }
-        };
-
-        map.insert(
-            key,
-            ProjectionCacheEntry::NormalizedTy(Normalized { value: ty, obligations: vec![] }),
-        );
-    }
-
-    /// A specialized version of `complete` for when the key's value is known
-    /// to be a NormalizedTy.
-    pub fn complete_normalized(&mut self, key: ProjectionCacheKey<'tcx>, ty: &NormalizedTy<'tcx>) {
-        // We want to insert `ty` with no obligations. If the existing value
-        // already has no obligations (as is common) we don't insert anything.
-        if !ty.obligations.is_empty() {
-            self.map().insert(
-                key,
-                ProjectionCacheEntry::NormalizedTy(Normalized {
-                    value: ty.value,
-                    obligations: vec![],
-                }),
-            );
-        }
-    }
-
     /// Indicates that trying to normalize `key` resulted in
     /// ambiguity. No point in trying it again then until we gain more
     /// type information (in which case, the "fully resolved" key will
index e76fa6d8a1bc664b7002a429e18e6ff797dc3e06..07af2201f5fc2a1222dc428abafc523957d1d3d7 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_interface"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 3b852b8ccf9d0ffffb47e80769ac77abe64113da..95bd2993456abcd2d4c64c3317db3c87ed4996ce 100644 (file)
@@ -25,6 +25,16 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result
     })
 }
 
+fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
+    tls::with_opt(|tcx| {
+        if let Some(tcx) = tcx {
+            let _span = tcx.source_span(def_id);
+            // Sanity check: relative span's parent must be an absolute span.
+            debug_assert_eq!(_span.data_untracked().parent, None);
+        }
+    })
+}
+
 /// This is a callback from `rustc_ast` as it cannot access the implicit state
 /// in `rustc_middle` otherwise. It is used to when diagnostic messages are
 /// emitted and stores them in the current query, if there is one.
@@ -56,6 +66,7 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) ->
 /// TyCtxt in.
 pub fn setup_callbacks() {
     rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+    rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
     rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
     TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
 }
index 1f3d6f70ff8373990e8ff45cf997aa371f401b98..cb7529b527e8f885e322afd9c9988c40f6a0c5f5 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
-use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
+use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
@@ -861,7 +861,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                 CStore::from_tcx(tcx).report_unused_deps(tcx);
             },
             {
-                par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+                tcx.hir().par_for_each_module(|module| {
                     tcx.ensure().check_mod_loops(module);
                     tcx.ensure().check_mod_attrs(module);
                     tcx.ensure().check_mod_naked_functions(module);
@@ -893,7 +893,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
             },
             {
                 sess.time("liveness_and_intrinsic_checking", || {
-                    par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+                    tcx.hir().par_for_each_module(|module| {
                         // this must run before MIR dump, because
                         // "not all control paths return a value" is reported here.
                         //
@@ -963,7 +963,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
             },
             {
                 sess.time("privacy_checking_modules", || {
-                    par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
+                    tcx.hir().par_for_each_module(|module| {
                         tcx.ensure().check_mod_privacy(module);
                     });
                 });
index afab919bc3c2cff582ac90614c5f6d3a7bc9fc51..cfe13b1fd4e1fbd060e37dbefb7229f00098435d 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!(panic_in_drop, PanicStrategy::Abort);
     tracked!(partially_uninit_const_threshold, Some(123));
     tracked!(plt, Some(true));
     tracked!(polonius, true);
@@ -753,6 +754,7 @@ macro_rules! tracked {
     tracked!(profiler_runtime, "abc".to_string());
     tracked!(relax_elf_relocations, Some(true));
     tracked!(relro_level, Some(RelroLevel::Full));
+    tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
     tracked!(report_delayed_bugs, true);
     tracked!(sanitizer, SanitizerSet::ADDRESS);
index a5f0c01477898dd6b2248a078026687c7b4338ad..3d90a6c9345362d5c4875202661d8a813eeee1e5 100644 (file)
@@ -125,6 +125,7 @@ unsafe impl Sync for Ptr {}
     let result_ptr = Ptr(&mut result as *mut _ as *mut ());
 
     let thread = cfg.spawn(move || {
+        let _ = (&run, &result_ptr);
         let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() };
         let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) };
         *result = Some(run());
index 7e05fe545cabe580987dd4092fffefe67eb7b6cb..60c146f457b42afc0dcd2f849d1aba70476f7836 100644 (file)
@@ -2,7 +2,7 @@
 name = "rustc_lexer"
 version = "0.1.0"
 license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
 
 repository = "https://github.com/rust-lang/rust/"
 description = """
index 8294d5878fa99015efaee012ac8a5eb2c049fe22..414fcbeb9e415d57706461952f1a126fcbce78df 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_lint"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 if_chain = "1.0"
index 5ac42c50c7240d22edb1adbd1b775248ac89d3fc..1facd973754331c08da5d1c4af5b92d801d29d2a 100644 (file)
@@ -13,7 +13,7 @@
     ///
     /// ### Example
     ///
-    /// ```rust
+    /// ```rust,edition2018
     /// # #![allow(unused)]
     /// [1, 2, 3].into_iter().for_each(|n| { *n; });
     /// ```
index 2850e7a6b44e95a485046701b98911e75a897ca3..e1bcc3aa52bc643dae02e9b7eed4385b0030c457 100644 (file)
@@ -1686,7 +1686,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
     ///
     /// ### Example
     ///
-    /// ```rust
+    /// ```rust,edition2018
     /// let x = 123;
     /// match x {
     ///     0...100 => {}
index 2070fd69d3f8eb7f59e75683e735b5ea2a774aba..00c3a6fa25e027e3ca811059b3d1b390d2324158 100644 (file)
@@ -16,7 +16,7 @@
 
 use crate::{passes::LateLintPassObject, LateContext, LateLintPass, LintStore};
 use rustc_ast as ast;
-use rustc_data_structures::sync::{join, par_iter, ParallelIterator};
+use rustc_data_structures::sync::join;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit as hir_visit;
@@ -501,9 +501,7 @@ pub fn check_crate<'tcx, T: LateLintPass<'tcx>>(
         || {
             tcx.sess.time("module_lints", || {
                 // Run per-module lints
-                par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {
-                    tcx.ensure().lint_mod(module);
-                });
+                tcx.hir().par_for_each_module(|module| tcx.ensure().lint_mod(module));
             });
         },
     );
index 33a6edafa26408185baf547c2bebb13b0e5bbab5..ae9c5ce5c3c2bdeff8c4f31dbecb81ebe128ce84 100644 (file)
@@ -18,7 +18,7 @@
     ///
     /// ### Example
     ///
-    /// ```rust,no_run
+    /// ```rust,no_run,edition2018
     /// panic!("{}");
     /// panic!(123);
     /// ```
index edb158dd378063228b0376003854828459ac59f2..5435ff1396de800c0841de33c4c74ae4dbfb9df0 100644 (file)
@@ -86,6 +86,7 @@
 
 impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+        use rustc_middle::ty;
         use rustc_middle::ty::PredicateKind::*;
 
         let predicates = cx.tcx.explicit_predicates_of(item.def_id);
@@ -94,6 +95,10 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
                 Trait(trait_predicate) => trait_predicate,
                 _ => continue,
             };
+            if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
+                // `~const Drop` definitely have meanings so avoid linting here.
+                continue;
+            }
             let def_id = trait_predicate.trait_ref.def_id;
             if cx.tcx.lang_items().drop_trait() == Some(def_id) {
                 // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern.
index 480f7756db3fe60476d766bc46ebffd852c38cf6..d35497c1b381a5460b359e76eb1e43e01eaffd2d 100644 (file)
@@ -851,12 +851,18 @@ fn check_variant_for_ffi(
         use FfiResult::*;
 
         if def.repr.transparent() {
-            // Can assume that only one field is not a ZST, so only check
+            // Can assume that at most one field is not a ZST, so only check
             // that field's type for FFI-safety.
             if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
                 self.check_field_type_for_ffi(cache, field, substs)
             } else {
-                bug!("malformed transparent type");
+                // All fields are ZSTs; this means that the type should behave
+                // like (), which is FFI-unsafe
+                FfiUnsafe {
+                    ty,
+                    reason: "this struct contains only zero-sized fields".into(),
+                    help: None,
+                }
             }
         } else {
             // We can't completely trust repr(C) markings; make sure the fields are
@@ -1327,10 +1333,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
             };
             let (variants, tag) = match layout.variants {
                 Variants::Multiple {
-                    tag_encoding: TagEncoding::Direct,
-                    ref tag,
-                    ref variants,
-                    ..
+                    tag_encoding: TagEncoding::Direct, tag, ref variants, ..
                 } => (variants, tag),
                 _ => return,
             };
index 7a42e8c1037ba3dc58105a56a57d9368aa7b2a86..48b955e41ac69506c05e5e46b071c979293dd6d3 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_ast as ast;
 use rustc_ast::util::{classify, parser};
 use rustc_ast::{ExprKind, StmtKind};
-use rustc_ast_pretty::pprust;
 use rustc_errors::{pluralize, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -12,7 +11,7 @@
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
@@ -491,77 +490,60 @@ fn emit_unused_delims_expr(
         left_pos: Option<BytePos>,
         right_pos: Option<BytePos>,
     ) {
-        let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-            snippet
-        } else {
-            pprust::expr_to_string(value)
+        let spans = match value.kind {
+            ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
+                let start = block.stmts[0].span;
+                let end = block.stmts[block.stmts.len() - 1].span;
+                if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
+                    (
+                        value.span.with_hi(value.span.lo() + BytePos(1)),
+                        value.span.with_lo(value.span.hi() - BytePos(1)),
+                    )
+                } else {
+                    (value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
+                }
+            }
+            ast::ExprKind::Paren(ref expr) => {
+                if value.span.from_expansion() || expr.span.from_expansion() {
+                    (
+                        value.span.with_hi(value.span.lo() + BytePos(1)),
+                        value.span.with_lo(value.span.hi() - BytePos(1)),
+                    )
+                } else {
+                    (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
+                }
+            }
+            _ => return,
         };
         let keep_space = (
             left_pos.map_or(false, |s| s >= value.span.lo()),
             right_pos.map_or(false, |s| s <= value.span.hi()),
         );
-        self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
+        self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
     }
 
     fn emit_unused_delims(
         &self,
         cx: &EarlyContext<'_>,
-        span: Span,
-        pattern: &str,
+        spans: (Span, Span),
         msg: &str,
         keep_space: (bool, bool),
     ) {
         // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
         // properly.
-        if span == DUMMY_SP {
+        if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
             return;
         }
 
-        cx.struct_span_lint(self.lint(), span, |lint| {
+        cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
             let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
             let mut err = lint.build(&span_msg);
-            let mut ate_left_paren = false;
-            let mut ate_right_paren = false;
-            let parens_removed = pattern
-                .trim_matches(|c| match c {
-                    '(' | '{' => {
-                        if ate_left_paren {
-                            false
-                        } else {
-                            ate_left_paren = true;
-                            true
-                        }
-                    }
-                    ')' | '}' => {
-                        if ate_right_paren {
-                            false
-                        } else {
-                            ate_right_paren = true;
-                            true
-                        }
-                    }
-                    _ => false,
-                })
-                .trim();
-
-            let replace = {
-                let mut replace = if keep_space.0 {
-                    let mut s = String::from(" ");
-                    s.push_str(parens_removed);
-                    s
-                } else {
-                    String::from(parens_removed)
-                };
-
-                if keep_space.1 {
-                    replace.push(' ');
-                }
-                replace
-            };
-
+            let replacement = vec![
+                (spans.0, if keep_space.0 { " ".into() } else { "".into() }),
+                (spans.1, if keep_space.1 { " ".into() } else { "".into() }),
+            ];
             let suggestion = format!("remove these {}", Self::DELIM_STR);
-
-            err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable);
+            err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable);
             err.emit();
         });
     }
@@ -770,14 +752,15 @@ fn check_unused_parens_pat(
                 // Otherwise proceed with linting.
                 _ => {}
             }
-
-            let pattern_text =
-                if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-                    snippet
-                } else {
-                    pprust::pat_to_string(value)
-                };
-            self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false));
+            let spans = if value.span.from_expansion() || inner.span.from_expansion() {
+                (
+                    value.span.with_hi(value.span.lo() + BytePos(1)),
+                    value.span.with_lo(value.span.hi() - BytePos(1)),
+                )
+            } else {
+                (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
+            };
+            self.emit_unused_delims(cx, spans, "pattern", (false, false));
         }
     }
 }
@@ -870,14 +853,15 @@ fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
                     );
                 }
                 _ => {
-                    let pattern_text =
-                        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) {
-                            snippet
-                        } else {
-                            pprust::ty_to_string(ty)
-                        };
-
-                    self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false));
+                    let spans = if ty.span.from_expansion() || r.span.from_expansion() {
+                        (
+                            ty.span.with_hi(ty.span.lo() + BytePos(1)),
+                            ty.span.with_lo(ty.span.hi() - BytePos(1)),
+                        )
+                    } else {
+                        (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
+                    };
+                    self.emit_unused_delims(cx, spans, "type", (false, false));
                 }
             }
         }
index f9ada5cc95f58c8cd7759272ac48c68f7b8059ce..798d50819e2d8b8449c5a74c10e9e9e97aee2bd5 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_lint_defs"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 rustc_ast = { path = "../rustc_ast" }
index 8fb678e2d20fb0313633d4b9adccfdf41ab8e4f3..b14abb9e5db48a46dce242ffac741a85de944d00 100644 (file)
     ///
     /// ### Example
     ///
-    /// ```rust
+    /// ```rust,edition2018
     /// trait Trait { }
     ///
     /// fn takes_trait_object(_: Box<Trait>) {
         UNSUPPORTED_CALLING_CONVENTIONS,
         BREAK_WITH_LABEL_AND_LOOP,
         UNUSED_ATTRIBUTES,
+        NON_EXHAUSTIVE_OMITTED_PATTERNS,
     ]
 }
 
     ///
     /// ### Example
     ///
-    /// ```rust,compile_fail
+    /// ```rust,edition2018,compile_fail
     /// #![deny(rust_2021_prefixes_incompatible_syntax)]
     ///
     /// macro_rules! m {
     ///
     /// This lint suggests to add whitespace between the `z` and `"hey"` tokens
     /// to keep them separated in Rust 2021.
+    // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser.
+    #[allow(rustdoc::invalid_rust_codeblocks)]
     pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
     Allow,
     "identifiers that will be parsed as a prefix in Rust 2021",
     Warn,
     "`break` expression with label and unlabeled loop as value expression"
 }
+
+declare_lint! {
+    /// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a
+    /// pattern for a `#[non_exhaustive]` struct or enum is reachable.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs separate crate)
+    /// // crate A
+    /// #[non_exhaustive]
+    /// pub enum Bar {
+    ///     A,
+    ///     B, // added variant in non breaking change
+    /// }
+    ///
+    /// // in crate B
+    /// match Bar::A {
+    ///     Bar::A => {},
+    ///     #[warn(non_exhaustive_omitted_patterns)]
+    ///     _ => {},
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// warning: reachable patterns not covered of non exhaustive enum
+    ///    --> $DIR/reachable-patterns.rs:70:9
+    ///    |
+    /// LL |         _ => {}
+    ///    |         ^ pattern `B` not covered
+    ///    |
+    ///  note: the lint level is defined here
+    ///   --> $DIR/reachable-patterns.rs:69:16
+    ///    |
+    /// LL |         #[warn(non_exhaustive_omitted_patterns)]
+    ///    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///    = help: ensure that all possible cases are being handled by adding the suggested match arms
+    ///    = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a
+    /// (potentially redundant) wildcard when pattern-matching, to allow for future
+    /// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint
+    /// detects when such a wildcard happens to actually catch some fields/variants.
+    /// In other words, when the match without the wildcard would not be exhaustive.
+    /// This lets the user be informed if new fields/variants were added.
+    pub NON_EXHAUSTIVE_OMITTED_PATTERNS,
+    Allow,
+    "detect when patterns of types marked `non_exhaustive` are missed",
+}
index 2f0f3dd9ecbb9eaf8e7e316a03d7434a73a7d7d5..d8dfcc84e68da444575638816b3ae1ba5a104718 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_llvm"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [features]
 static-libstdcpp = []
index 964b7cace9cd4e45326377d62d7a0a0e1616808a..36a6d2cc33a99936b53df8c3566798683c9c71fb 100644 (file)
@@ -76,6 +76,7 @@ fn main() {
         "aarch64",
         "amdgpu",
         "avr",
+        "m68k",
         "mips",
         "powerpc",
         "systemz",
index b3f86f3295ae90f602a1f5272f7221956815d56d..8dbacd71fc13892ee3877fa6ac4e987875de97ba 100644 (file)
@@ -201,6 +201,12 @@ void LLVMRustAddLastExtensionPasses(
 #define SUBTARGET_AVR
 #endif
 
+#ifdef LLVM_COMPONENT_M68k
+#define SUBTARGET_M68K SUBTARGET(M68k)
+#else
+#define SUBTARGET_M68K
+#endif
+
 #ifdef LLVM_COMPONENT_MIPS
 #define SUBTARGET_MIPS SUBTARGET(Mips)
 #else
@@ -248,6 +254,7 @@ void LLVMRustAddLastExtensionPasses(
   SUBTARGET_ARM                                                                \
   SUBTARGET_AARCH64                                                            \
   SUBTARGET_AVR                                                                \
+  SUBTARGET_M68K                                                               \
   SUBTARGET_MIPS                                                               \
   SUBTARGET_PPC                                                                \
   SUBTARGET_SYSTEMZ                                                            \
@@ -875,7 +882,11 @@ LLVMRustOptimizeWithNewPassManager(
 #if LLVM_VERSION_GE(11, 0)
       OptimizerLastEPCallbacks.push_back(
         [Options](ModulePassManager &MPM, OptimizationLevel Level) {
+#if LLVM_VERSION_GE(14, 0)
+          MPM.addPass(ModuleMemorySanitizerPass(Options));
+#else
           MPM.addPass(MemorySanitizerPass(Options));
+#endif
           MPM.addPass(createModuleToFunctionPassAdaptor(MemorySanitizerPass(Options)));
         }
       );
@@ -897,7 +908,11 @@ LLVMRustOptimizeWithNewPassManager(
 #if LLVM_VERSION_GE(11, 0)
       OptimizerLastEPCallbacks.push_back(
         [](ModulePassManager &MPM, OptimizationLevel Level) {
+#if LLVM_VERSION_GE(14, 0)
+          MPM.addPass(ModuleThreadSanitizerPass());
+#else
           MPM.addPass(ThreadSanitizerPass());
+#endif
           MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
         }
       );
index 4f07a0c67c13f43f50b1962a992b0c9b6ad50136..9850f395a0f650a05d9bbb3e06ddb24b248e17d1 100644 (file)
@@ -203,56 +203,57 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
   report_fatal_error("bad AttributeKind");
 }
 
+template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
+#if LLVM_VERSION_LT(14, 0)
+  t->addAttribute(Index, Attr);
+#else
+  t->addAttributeAtIndex(Index, Attr);
+#endif
+}
+
 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
                                               const char *Name) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), Name);
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
-
 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
                                                  unsigned Index,
                                                  uint32_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addAlignmentAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
                                                        unsigned Index,
                                                        uint64_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addDereferenceableAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
                                                              unsigned Index,
                                                              uint64_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addDereferenceableOrNullAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
                                              LLVMTypeRef Ty) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
@@ -263,28 +264,28 @@ extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned In
 #else
   Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
 #endif
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
   Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
-  A->addAttribute(Index, Attr);
+  AddAttribute(A, Index, Attr);
 }
 
 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
                                          unsigned Index,
                                          uint32_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithAlignment(
+  AddAttribute(A, Index, Attribute::getWithAlignment(
       A->getContext(), llvm::Align(Bytes)));
 }
 
 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
                                                uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(),
+  AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
                                                                 Bytes));
 }
 
@@ -292,7 +293,7 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
                                                      unsigned Index,
                                                      uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes(
+  AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
       A->getContext(), Bytes));
 }
 
@@ -300,7 +301,7 @@ extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
                                      LLVMTypeRef Ty) {
   Function *F = unwrap<Function>(Fn);
   Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
-  F->addAttribute(Index, Attr);
+  AddAttribute(F, Index, Attr);
 }
 
 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
@@ -311,7 +312,7 @@ extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
 #else
   Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet);
 #endif
-  F->addAttribute(Index, Attr);
+  AddAttribute(F, Index, Attr);
 }
 
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
@@ -319,7 +320,7 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    const char *Name,
                                                    const char *Value) {
   Function *F = unwrap<Function>(Fn);
-  F->addAttribute(Index, Attribute::get(
+  AddAttribute(F, Index, Attribute::get(
       F->getContext(), StringRef(Name), StringRef(Value)));
 }
 
@@ -330,7 +331,12 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
   Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
   auto PAL = F->getAttributes();
-  auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+  AttributeList PALNew;
+#if LLVM_VERSION_LT(14, 0)
+  PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+#else
+  PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B);
+#endif
   F->setAttributes(PALNew);
 }
 
index 122627eb500ada1b69f2d38924d63e9f4069dcc9..2f199989d3b214f467ef17760e7697c0e62e7348 100644 (file)
@@ -90,6 +90,14 @@ fn init() { }
         LLVMInitializeAVRAsmPrinter,
         LLVMInitializeAVRAsmParser
     );
+    init_target!(
+        llvm_component = "m68k",
+        LLVMInitializeM68kTargetInfo,
+        LLVMInitializeM68kTarget,
+        LLVMInitializeM68kTargetMC,
+        LLVMInitializeM68kAsmPrinter,
+        LLVMInitializeM68kAsmParser
+    );
     init_target!(
         llvm_component = "mips",
         LLVMInitializeMipsTargetInfo,
index e4dddbab06755245143214d8772b8d05718a5a73..a9192be4d6ef43f00574dac372fc45970d74d0f4 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_macros"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 proc-macro = true
index 8a0fce209b7fbeb0a9b6ddfea32a78c909864d61..80dcf99da6224b775936e1b1d746e89a640987c1 100644 (file)
@@ -448,7 +448,7 @@ fn generate_non_option_field_code(
                                             span_idx = Some(syn::Index::from(idx));
                                         } else {
                                             throw_span_err!(
-                                                info.span.clone().unwrap(),
+                                                info.span.unwrap(),
                                                 "type of field annotated with `#[suggestion(...)]` contains more than one Span"
                                             );
                                         }
@@ -460,7 +460,7 @@ fn generate_non_option_field_code(
                                             applicability_idx = Some(syn::Index::from(idx));
                                         } else {
                                             throw_span_err!(
-                                                info.span.clone().unwrap(),
+                                                info.span.unwrap(),
                                                 "type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
                                             );
                                         }
@@ -479,7 +479,7 @@ fn generate_non_option_field_code(
                                     return Ok((span, applicability));
                                 }
                                 throw_span_err!(
-                                    info.span.clone().unwrap(),
+                                    info.span.unwrap(),
                                     "wrong types for suggestion",
                                     |diag| {
                                         diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)")
@@ -487,7 +487,7 @@ fn generate_non_option_field_code(
                                 );
                             }
                             _ => throw_span_err!(
-                                info.span.clone().unwrap(),
+                                info.span.unwrap(),
                                 "wrong field type for suggestion",
                                 |diag| {
                                     diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)")
index 85e990bde86dc0d2f842e8d86516587766a9f1ba..1b245f2a7506080f1d5de9aa83cde69cd67ddb33 100644 (file)
@@ -215,7 +215,7 @@ pub mod sym_generated {
         }
 
         impl Interner {
-            pub fn fresh() -> Self {
+            pub(crate) fn fresh() -> Self {
                 Interner::prefill(&[
                     #prefill_stream
                 ])
index 7c79aa5e00bba3155279b0dcedf36234df3b69b7..f71fefd17992083d4bd026199d7c3ca4e10e07fb 100644 (file)
@@ -1,13 +1,14 @@
 [package]
 name = "rustc_metadata"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
 
 [dependencies]
 libc = "0.2"
+odht = { version = "0.3.0", features = ["nightly"] }
 snap = "1"
 tracing = "0.1"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
index 99030febb7380210e25fbf2bedecada294f7d3bf..48d8cdf57dcfcd348421a3c0f7f1a145b55ea984 100644 (file)
@@ -45,7 +45,7 @@ pub struct CStore {
 
     /// This map is used to verify we get no hash conflicts between
     /// `StableCrateId` values.
-    stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
+    pub(crate) stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
 
     /// Unused externs of the crate
     unused_externs: Vec<Symbol>,
index 2d4deb1d8d5da43d9a2e19bdf5d8b32aad0c2383..8c41fd9c4a2373901e72c48d407fff782462a63f 100644 (file)
 //! should be used when linking each output type requested in this session. This
 //! generally follows this set of rules:
 //!
-//!     1. Each library must appear exactly once in the output.
-//!     2. Each rlib contains only one library (it's just an object file)
-//!     3. Each dylib can contain more than one library (due to static linking),
-//!        and can also bring in many dynamic dependencies.
+//! 1. Each library must appear exactly once in the output.
+//! 2. Each rlib contains only one library (it's just an object file)
+//! 3. Each dylib can contain more than one library (due to static linking),
+//!    and can also bring in many dynamic dependencies.
 //!
 //! With these constraints in mind, it's generally a very difficult problem to
 //! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
 //!
 //! The current selection algorithm below looks mostly similar to:
 //!
-//!     1. If static linking is required, then require all upstream dependencies
-//!        to be available as rlibs. If not, generate an error.
-//!     2. If static linking is requested (generating an executable), then
-//!        attempt to use all upstream dependencies as rlibs. If any are not
-//!        found, bail out and continue to step 3.
-//!     3. Static linking has failed, at least one library must be dynamically
-//!        linked. Apply a heuristic by greedily maximizing the number of
-//!        dynamically linked libraries.
-//!     4. Each upstream dependency available as a dynamic library is
-//!        registered. The dependencies all propagate, adding to a map. It is
-//!        possible for a dylib to add a static library as a dependency, but it
-//!        is illegal for two dylibs to add the same static library as a
-//!        dependency. The same dylib can be added twice. Additionally, it is
-//!        illegal to add a static dependency when it was previously found as a
-//!        dylib (and vice versa)
-//!     5. After all dynamic dependencies have been traversed, re-traverse the
-//!        remaining dependencies and add them statically (if they haven't been
-//!        added already).
+//! 1. If static linking is required, then require all upstream dependencies
+//!    to be available as rlibs. If not, generate an error.
+//! 2. If static linking is requested (generating an executable), then
+//!    attempt to use all upstream dependencies as rlibs. If any are not
+//!    found, bail out and continue to step 3.
+//! 3. Static linking has failed, at least one library must be dynamically
+//!    linked. Apply a heuristic by greedily maximizing the number of
+//!    dynamically linked libraries.
+//! 4. Each upstream dependency available as a dynamic library is
+//!    registered. The dependencies all propagate, adding to a map. It is
+//!    possible for a dylib to add a static library as a dependency, but it
+//!    is illegal for two dylibs to add the same static library as a
+//!    dependency. The same dylib can be added twice. Additionally, it is
+//!    illegal to add a static dependency when it was previously found as a
+//!    dylib (and vice versa)
+//! 5. After all dynamic dependencies have been traversed, re-traverse the
+//!    remaining dependencies and add them statically (if they haven't been
+//!    added already).
 //!
 //! While not perfect, this algorithm should help support use-cases such as leaf
 //! dependencies being static while the larger tree of inner dependencies are
@@ -400,21 +400,35 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
                 continue;
             }
             let cnum = CrateNum::new(i + 1);
-            let found_strategy = tcx.panic_strategy(cnum);
-            let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
-            if is_compiler_builtins || desired_strategy == found_strategy {
+            if tcx.is_compiler_builtins(cnum) {
                 continue;
             }
 
-            sess.err(&format!(
-                "the crate `{}` is compiled with the \
+            let found_strategy = tcx.panic_strategy(cnum);
+            if desired_strategy != found_strategy {
+                sess.err(&format!(
+                    "the crate `{}` is compiled with the \
                                panic strategy `{}` which is \
                                incompatible with this crate's \
                                strategy of `{}`",
-                tcx.crate_name(cnum),
-                found_strategy.desc(),
-                desired_strategy.desc()
-            ));
+                    tcx.crate_name(cnum),
+                    found_strategy.desc(),
+                    desired_strategy.desc()
+                ));
+            }
+
+            let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
+            if tcx.sess.opts.debugging_opts.panic_in_drop != found_drop_strategy {
+                sess.err(&format!(
+                    "the crate `{}` is compiled with the \
+                               panic-in-drop strategy `{}` which is \
+                               incompatible with this crate's \
+                               strategy of `{}`",
+                    tcx.crate_name(cnum),
+                    found_drop_strategy.desc(),
+                    tcx.sess.opts.debugging_opts.panic_in_drop.desc()
+                ));
+            }
         }
     }
 }
index d3512b6cf579e18e1d0cd4d70914ae7c7d1f1231..b6922e0d72a065364c0e0444c70e961128ae5328 100644 (file)
@@ -1095,6 +1095,11 @@ impl CrateError {
                         == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime)
                     {
                         err.note(&"the compiler may have been built without the profiler runtime");
+                    } else if crate_name.as_str().starts_with("rustc_") {
+                        err.help(
+                            "maybe you need to install the missing components with: \
+                             `rustup component add rust-src rustc-dev llvm-tools-preview`",
+                        );
                     }
                     err.span_label(span, "can't find crate");
                     err
index 5f0d8c46f20dcd27eb0cb3a0972b9eb30a722ea1..5ad55dbf5c80d38ba9415413204d6aa34a9f3aea 100644 (file)
@@ -382,7 +382,7 @@ fn process_command_line(&mut self) {
         }
     }
 
-    fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+    fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
         let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
             self.tcx
                 .type_of(item.id.def_id)
@@ -406,7 +406,7 @@ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
             .sum()
     }
 
-    fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+    fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
         let calling_convention = if self.tcx.sess.target.arch == "x86" {
             match abi {
                 Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
index dd44e0cb1fa90872c1f64cad00ddb3d52bd75eb3..eb3a9f576a735429415e0d1e6198b296a33cf342 100644 (file)
@@ -26,6 +26,7 @@
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::mir::{self, Body, Promoted};
+use rustc_middle::thir;
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
 use rustc_serialize::{opaque, Decodable, Decoder};
 
 mod cstore_impl;
 
-crate struct MetadataBlob(MetadataRef);
+/// A reference to the raw binary version of crate metadata.
+/// A `MetadataBlob` internally is just a reference counted pointer to
+/// the actual data, so cloning it is cheap.
+#[derive(Clone)]
+crate struct MetadataBlob(Lrc<MetadataRef>);
+
+// This is needed so we can create an OwningRef into the blob.
+// The data behind a `MetadataBlob` has a stable address because it is
+// contained within an Rc/Arc.
+unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {}
+
+// This is needed so we can create an OwningRef into the blob.
+impl std::ops::Deref for MetadataBlob {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        &self.0[..]
+    }
+}
 
 // A map from external crate numbers (as decoded from some crate file) to
 // local crate numbers (as generated during this session). Each external
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
     source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
-    /// For every definition in this crate, maps its `DefPathHash` to its
-    /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
-    /// this is used.
-    def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
+    /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
+    def_path_hash_map: DefPathHashMapRef<'static>,
     /// Likewise for ExpnHash.
     expn_hash_map: OnceCell<UnhashMap<ExpnHash, ExpnIndex>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
@@ -133,6 +151,7 @@ struct ImportedSourceFile {
 pub(super) struct DecodeContext<'a, 'tcx> {
     opaque: opaque::Decoder<'a>,
     cdata: Option<CrateMetadataRef<'a>>,
+    blob: &'a MetadataBlob,
     sess: Option<&'tcx Session>,
     tcx: Option<TyCtxt<'tcx>>,
 
@@ -147,7 +166,8 @@ pub(super) struct DecodeContext<'a, 'tcx> {
 
 /// Abstract over the various ways one can create metadata decoders.
 pub(super) trait Metadata<'a, 'tcx>: Copy {
-    fn raw_bytes(self) -> &'a [u8];
+    fn blob(self) -> &'a MetadataBlob;
+
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         None
     }
@@ -161,8 +181,9 @@ fn tcx(self) -> Option<TyCtxt<'tcx>> {
     fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
         let tcx = self.tcx();
         DecodeContext {
-            opaque: opaque::Decoder::new(self.raw_bytes(), pos),
+            opaque: opaque::Decoder::new(self.blob(), pos),
             cdata: self.cdata(),
+            blob: self.blob(),
             sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
             tcx,
             last_source_file_index: 0,
@@ -175,17 +196,19 @@ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
-    fn raw_bytes(self) -> &'a [u8] {
-        &self.0
+    #[inline]
+    fn blob(self) -> &'a MetadataBlob {
+        self
     }
 }
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
-    fn raw_bytes(self) -> &'a [u8] {
-        let (blob, _) = self;
-        &blob.0
+    #[inline]
+    fn blob(self) -> &'a MetadataBlob {
+        self.0
     }
 
+    #[inline]
     fn sess(self) -> Option<&'tcx Session> {
         let (_, sess) = self;
         Some(sess)
@@ -193,33 +216,41 @@ fn sess(self) -> Option<&'tcx Session> {
 }
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
-    fn raw_bytes(self) -> &'a [u8] {
-        self.blob.raw_bytes()
+    #[inline]
+    fn blob(self) -> &'a MetadataBlob {
+        &self.blob
     }
+    #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         Some(*self)
     }
 }
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
-    fn raw_bytes(self) -> &'a [u8] {
-        self.0.raw_bytes()
+    #[inline]
+    fn blob(self) -> &'a MetadataBlob {
+        &self.0.blob
     }
+    #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         Some(*self.0)
     }
+    #[inline]
     fn sess(self) -> Option<&'tcx Session> {
         Some(&self.1)
     }
 }
 
 impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
-    fn raw_bytes(self) -> &'a [u8] {
-        self.0.raw_bytes()
+    #[inline]
+    fn blob(self) -> &'a MetadataBlob {
+        &self.0.blob
     }
+    #[inline]
     fn cdata(self) -> Option<CrateMetadataRef<'a>> {
         Some(*self.0)
     }
+    #[inline]
     fn tcx(self) -> Option<TyCtxt<'tcx>> {
         Some(self.1)
     }
@@ -245,12 +276,21 @@ fn decode<M: Metadata<'a, 'tcx>>(
 }
 
 impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
+    #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx.expect("missing TyCtxt in DecodeContext")
+        debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext");
+        self.tcx.unwrap()
+    }
+
+    #[inline]
+    pub fn blob(&self) -> &'a MetadataBlob {
+        self.blob
     }
 
-    fn cdata(&self) -> CrateMetadataRef<'a> {
-        self.cdata.expect("missing CrateMetadata in DecodeContext")
+    #[inline]
+    pub fn cdata(&self) -> CrateMetadataRef<'a> {
+        debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext");
+        self.cdata.unwrap()
     }
 
     fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
@@ -275,6 +315,11 @@ fn read_lazy_with_meta<T: ?Sized + LazyMeta>(
         self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap());
         Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta))
     }
+
+    #[inline]
+    pub fn read_raw_bytes(&mut self, len: usize) -> &'a [u8] {
+        self.opaque.read_raw_bytes(len)
+    }
 }
 
 impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
@@ -536,11 +581,12 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> {
         let hi =
             (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
 
-        Ok(Span::new(lo, hi, ctxt))
+        // Do not try to decode parent for foreign spans.
+        Ok(Span::new(lo, hi, ctxt, None))
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
         ty::codec::RefDecodable::decode(d)
     }
@@ -584,11 +630,11 @@ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
 
 impl MetadataBlob {
     crate fn new(metadata_ref: MetadataRef) -> MetadataBlob {
-        MetadataBlob(metadata_ref)
+        MetadataBlob(Lrc::new(metadata_ref))
     }
 
     crate fn is_compatible(&self) -> bool {
-        self.raw_bytes().starts_with(METADATA_HEADER)
+        self.blob().starts_with(METADATA_HEADER)
     }
 
     crate fn get_rustc_version(&self) -> String {
@@ -597,7 +643,7 @@ impl MetadataBlob {
     }
 
     crate fn get_root(&self) -> CrateRoot<'tcx> {
-        let slice = self.raw_bytes();
+        let slice = &self.blob()[..];
         let offset = METADATA_HEADER.len();
         let pos = (((slice[offset + 0] as u32) << 24)
             | ((slice[offset + 1] as u32) << 16)
@@ -1019,10 +1065,7 @@ fn get_diagnostic_items(&self) -> FxHashMap<Symbol, DefId> {
     }
 
     /// Iterates over each child of the given item.
-    fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
-    where
-        F: FnMut(Export<hir::HirId>),
-    {
+    fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) {
         if let Some(data) = &self.root.proc_macro_data {
             /* If we are loading as a proc macro, we want to return the view of this crate
              * as a proc macro crate.
@@ -1198,14 +1241,14 @@ fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> {
             .decode((self, tcx))
     }
 
-    fn get_mir_abstract_const(
+    fn get_thir_abstract_const(
         &self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         self.root
             .tables
-            .mir_abstract_consts
+            .thir_abstract_consts
             .get(self, id)
             .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
     }
@@ -1553,58 +1596,6 @@ fn def_key(&self, index: DefIndex) -> DefKey {
             .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self))
     }
 
-    /// Finds the corresponding `DefId` for the provided `DefPathHash`, if it exists.
-    /// This is used by incremental compilation to map a serialized `DefPathHash` to
-    /// its `DefId` in the current session.
-    /// Normally, only one 'main' crate will change between incremental compilation sessions:
-    /// all dependencies will be completely unchanged. In this case, we can avoid
-    /// decoding every `DefPathHash` in the crate, since the `DefIndex` from the previous
-    /// session will still be valid. If our 'guess' is wrong (the `DefIndex` no longer exists,
-    /// or has a different `DefPathHash`, then we need to decode all `DefPathHashes` to determine
-    /// the correct mapping).
-    fn def_path_hash_to_def_id(
-        &self,
-        krate: CrateNum,
-        index_guess: u32,
-        hash: DefPathHash,
-    ) -> Option<DefId> {
-        let def_index_guess = DefIndex::from_u32(index_guess);
-        let old_hash = self
-            .root
-            .tables
-            .def_path_hashes
-            .get(self, def_index_guess)
-            .map(|lazy| lazy.decode(self));
-
-        // Fast path: the definition and its index is unchanged from the
-        // previous compilation session. There is no need to decode anything
-        // else
-        if old_hash == Some(hash) {
-            return Some(DefId { krate, index: def_index_guess });
-        }
-
-        let is_proc_macro = self.is_proc_macro_crate();
-
-        // Slow path: We need to find out the new `DefIndex` of the provided
-        // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash`
-        // stored in this crate.
-        let map = self.cdata.def_path_hash_map.get_or_init(|| {
-            let end_id = self.root.tables.def_path_hashes.size() as u32;
-            let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
-            for i in 0..end_id {
-                let def_index = DefIndex::from_u32(i);
-                // There may be gaps in the encoded table if we're decoding a proc-macro crate
-                if let Some(hash) = self.root.tables.def_path_hashes.get(self, def_index) {
-                    map.insert(hash.decode(self), def_index);
-                } else if !is_proc_macro {
-                    panic!("Missing def_path_hashes entry for {:?}", def_index);
-                }
-            }
-            map
-        });
-        map.get(&hash).map(|index| DefId { krate, index: *index })
-    }
-
     // Returns the path leading to the thing with this `id`.
     fn def_path(&self, id: DefIndex) -> DefPath {
         debug!("def_path(cnum={:?}, id={:?})", self.cnum, id);
@@ -1627,6 +1618,11 @@ fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
         self.def_path_hash_unlocked(index, &mut def_path_hashes)
     }
 
+    #[inline]
+    fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> DefIndex {
+        self.def_path_hash_map.def_path_hash_to_def_index(&hash)
+    }
+
     fn expn_hash_to_expn_id(&self, index_guess: u32, hash: ExpnHash) -> ExpnId {
         debug_assert_eq!(ExpnId::from_hash(hash), None);
         let index_guess = ExpnIndex::from_u32(index_guess);
@@ -1893,13 +1889,18 @@ impl CrateMetadata {
         let alloc_decoding_state =
             AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
         let dependencies = Lock::new(cnum_map.iter().cloned().collect());
+
+        // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation
+        // that does not copy any data. It just does some data verification.
+        let def_path_hash_map = root.def_path_hash_map.decode(&blob);
+
         CrateMetadata {
             blob,
             root,
             trait_impls,
             raw_proc_macros,
             source_map_import_info: OnceCell::new(),
-            def_path_hash_map: Default::default(),
+            def_path_hash_map,
             expn_hash_map: Default::default(),
             alloc_decoding_state,
             cnum,
index 41839c58021ab335c7b2e4c4391d9631544b2834..70952d388d52d9fba6aed7960422085428600f43 100644 (file)
@@ -5,7 +5,6 @@
 
 use rustc_ast as ast;
 use rustc_data_structures::stable_map::FxHashMap;
-use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
@@ -117,7 +116,7 @@ fn into_args(self) -> (DefId, DefId) {
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
     mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
-    mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
+    thir_abstract_const => { cdata.get_thir_abstract_const(tcx, def_id.index) }
     unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
     const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
@@ -160,6 +159,7 @@ fn into_args(self) -> (DefId, DefId) {
     has_panic_handler => { cdata.root.has_panic_handler }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
+    panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy }
     extern_crate => {
         let r = *cdata.extern_crate.lock();
         r.map(|c| &*tcx.arena.alloc(c))
@@ -326,28 +326,27 @@ pub fn provide(providers: &mut Providers) {
             // (restrict scope of mutable-borrow of `visible_parent_map`)
             {
                 let visible_parent_map = &mut visible_parent_map;
-                let mut add_child =
-                    |bfs_queue: &mut VecDeque<_>, child: &Export<hir::HirId>, parent: DefId| {
-                        if child.vis != ty::Visibility::Public {
-                            return;
-                        }
+                let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
+                    if child.vis != ty::Visibility::Public {
+                        return;
+                    }
 
-                        if let Some(child) = child.res.opt_def_id() {
-                            match visible_parent_map.entry(child) {
-                                Entry::Occupied(mut entry) => {
-                                    // If `child` is defined in crate `cnum`, ensure
-                                    // that it is mapped to a parent in `cnum`.
-                                    if child.is_local() && entry.get().is_local() {
-                                        entry.insert(parent);
-                                    }
-                                }
-                                Entry::Vacant(entry) => {
+                    if let Some(child) = child.res.opt_def_id() {
+                        match visible_parent_map.entry(child) {
+                            Entry::Occupied(mut entry) => {
+                                // If `child` is defined in crate `cnum`, ensure
+                                // that it is mapped to a parent in `cnum`.
+                                if child.is_local() && entry.get().is_local() {
                                     entry.insert(parent);
-                                    bfs_queue.push_back(child);
                                 }
                             }
+                            Entry::Vacant(entry) => {
+                                entry.insert(parent);
+                                bfs_queue.push_back(child);
+                            }
                         }
-                    };
+                    }
+                };
 
                 while let Some(def) = bfs_queue.pop_front() {
                     for child in tcx.item_children(def).iter() {
@@ -393,11 +392,7 @@ pub fn visibility_untracked(&self, def: DefId) -> Visibility {
         self.get_crate_data(def.krate).get_visibility(def.index)
     }
 
-    pub fn item_children_untracked(
-        &self,
-        def_id: DefId,
-        sess: &Session,
-    ) -> Vec<Export<hir::HirId>> {
+    pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<Export> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate).each_child_of_item(
             def_id.index,
@@ -503,6 +498,10 @@ fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId {
         self.get_crate_data(cnum).root.stable_crate_id
     }
 
+    fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum {
+        self.stable_crate_ids[&stable_crate_id]
+    }
+
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
@@ -518,14 +517,9 @@ fn def_path_hash(&self, def: DefId) -> DefPathHash {
         self.get_crate_data(def.krate).def_path_hash(def.index)
     }
 
-    // See `CrateMetadataRef::def_path_hash_to_def_id` for more details
-    fn def_path_hash_to_def_id(
-        &self,
-        cnum: CrateNum,
-        index_guess: u32,
-        hash: DefPathHash,
-    ) -> Option<DefId> {
-        self.get_crate_data(cnum).def_path_hash_to_def_id(cnum, index_guess, hash)
+    fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId {
+        let def_index = self.get_crate_data(cnum).def_path_hash_to_def_index(hash);
+        DefId { krate: cnum, index: def_index }
     }
 
     fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId {
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
new file mode 100644 (file)
index 0000000..d6435bb
--- /dev/null
@@ -0,0 +1,58 @@
+use crate::rmeta::DecodeContext;
+use crate::rmeta::EncodeContext;
+use crate::rmeta::MetadataBlob;
+use rustc_data_structures::owning_ref::OwningRef;
+use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
+use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_span::def_id::{DefIndex, DefPathHash};
+
+crate enum DefPathHashMapRef<'tcx> {
+    OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>),
+    BorrowedFromTcx(&'tcx DefPathHashMap),
+}
+
+impl DefPathHashMapRef<'tcx> {
+    #[inline]
+    pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex {
+        match *self {
+            DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(def_path_hash).unwrap(),
+            DefPathHashMapRef::BorrowedFromTcx(_) => {
+                panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization")
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefPathHashMapRef<'tcx> {
+    fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+        match *self {
+            DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => {
+                let bytes = def_path_hash_map.raw_bytes();
+                e.emit_usize(bytes.len())?;
+                e.emit_raw_bytes(bytes)
+            }
+            DefPathHashMapRef::OwnedFromMetadata(_) => {
+                panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization")
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static> {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefPathHashMapRef<'static>, String> {
+        // Import TyDecoder so we can access the DecodeContext::position() method
+        use crate::rustc_middle::ty::codec::TyDecoder;
+
+        let len = d.read_usize()?;
+        let pos = d.position();
+        let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]);
+
+        // Although we already have the data we need via the OwningRef, we still need
+        // to advance the DecodeContext's position so it's in a valid state after
+        // the method. We use read_raw_bytes() for that.
+        let _ = d.read_raw_bytes(len);
+
+        let inner = odht::HashTable::from_raw_bytes(o).map_err(|e| format!("{}", e))?;
+        Ok(DefPathHashMapRef::OwnedFromMetadata(inner))
+    }
+}
index d8b9a4799760ef3d9cf79db8932c527a512de6ae..a50c4549d3d3fbe8a1334e73c3801d79ca08ee34 100644 (file)
@@ -1,3 +1,4 @@
+use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
 use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
 use crate::rmeta::*;
 
@@ -23,6 +24,7 @@
     metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
 };
 use rustc_middle::mir::interpret;
+use rustc_middle::thir;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
@@ -344,7 +346,7 @@ fn encode_alloc_id(
     }
 }
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
         (**self).encode(s)
     }
@@ -471,6 +473,12 @@ fn encode_def_path_table(&mut self) {
         }
     }
 
+    fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> {
+        self.lazy(DefPathHashMapRef::BorrowedFromTcx(
+            self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(),
+        ))
+    }
+
     fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
         let source_map = self.tcx.sess.source_map();
         let all_source_files = source_map.files();
@@ -674,6 +682,10 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
         let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
         let hygiene_bytes = self.position() - i;
 
+        i = self.position();
+        let def_path_hash_map = self.encode_def_path_hash_map();
+        let def_path_hash_map_bytes = self.position() - i;
+
         // Encode source_map. This needs to be done last,
         // since encoding `Span`s tells us which `SourceFiles` we actually
         // need to encode.
@@ -691,6 +703,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             hash: tcx.crate_hash(LOCAL_CRATE),
             stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
             panic_strategy: tcx.sess.panic_strategy(),
+            panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop,
             edition: tcx.sess.edition(),
             has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
             has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
@@ -720,6 +733,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             syntax_contexts,
             expn_data,
             expn_hashes,
+            def_path_hash_map,
         });
 
         let total_bytes = self.position();
@@ -742,6 +756,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             eprintln!("            impl bytes: {}", impl_bytes);
             eprintln!("    exp. symbols bytes: {}", exported_symbols_bytes);
             eprintln!("  def-path table bytes: {}", def_path_table_bytes);
+            eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes);
             eprintln!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
             eprintln!("             mir bytes: {}", mir_bytes);
             eprintln!("            item bytes: {}", item_bytes);
@@ -1065,14 +1080,7 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
         // items - we encode information about proc-macros later on.
         let reexports = if !self.is_proc_macro {
             match tcx.module_exports(local_def_id) {
-                Some(exports) => {
-                    let hir = self.tcx.hir();
-                    self.lazy(
-                        exports
-                            .iter()
-                            .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))),
-                    )
-                }
+                Some(exports) => self.lazy(exports),
                 _ => Lazy::empty(),
             }
         } else {
@@ -1304,9 +1312,10 @@ fn encode_mir(&mut self) {
             if encode_const {
                 record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
 
-                let abstract_const = self.tcx.mir_abstract_const(def_id);
+                // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
+                let abstract_const = self.tcx.thir_abstract_const(def_id);
                 if let Ok(Some(abstract_const)) = abstract_const {
-                    record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
+                    record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const);
                 }
             }
             record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
index a487753f4628a4548275019870d0eaf0c9336982..eb2bd80f46e64686715184798f10db490e3935e0 100644 (file)
@@ -1,4 +1,5 @@
 use decoder::Metadata;
+use def_path_hash_map::DefPathHashMapRef;
 use table::{Table, TableBuilder};
 
 use rustc_ast::{self as ast, MacroDef};
@@ -15,6 +16,7 @@
 use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir;
+use rustc_middle::thir;
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
@@ -34,6 +36,7 @@
 use rustc_span::hygiene::SyntaxContextData;
 
 mod decoder;
+mod def_path_hash_map;
 mod encoder;
 mod table;
 
@@ -204,6 +207,7 @@ macro_rules! Lazy {
     hash: Svh,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
+    panic_in_drop_strategy: PanicStrategy,
     edition: Edition,
     has_global_allocator: bool,
     has_panic_handler: bool,
@@ -229,6 +233,8 @@ macro_rules! Lazy {
     expn_data: ExpnDataTable,
     expn_hashes: ExpnHashTable,
 
+    def_path_hash_map: Lazy<DefPathHashMapRef<'tcx>>,
+
     source_map: Lazy<[rustc_span::SourceFile]>,
 
     compiler_builtins: bool,
@@ -305,7 +311,7 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> {
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
-    mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
+    thir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>,
     const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
     // `def_keys` and `def_path_hashes` represent a lazy version of a
@@ -359,7 +365,7 @@ enum EntryKind {
 
 #[derive(MetadataEncodable, MetadataDecodable)]
 struct ModData {
-    reexports: Lazy<[Export<hir::HirId>]>,
+    reexports: Lazy<[Export]>,
     expansion: ExpnId,
 }
 
index 62c0ce1584594afdb3d85d9b5b57bd2d15adc941..4dfefda490b3deeea6878c4f97787aecd747da5c 100644 (file)
@@ -199,7 +199,7 @@ pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) ->
         debug!("Table::lookup: index={:?} len={:?}", i, self.meta);
 
         let start = self.position.get();
-        let bytes = &metadata.raw_bytes()[start..start + self.meta];
+        let bytes = &metadata.blob()[start..start + self.meta];
         <Option<T>>::maybe_read_from_bytes_at(bytes, i.index())?
     }
 
index 68b83fccc85fd4dd1f98c49996c1564c91a6732c..b1fcc34bee1d7d68884b397c8d817d1a9ada9115 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_middle"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 59db2c6636ff9e8495c612ab69c737a7b962b446..2dd43a4e8522d0e0a3dacb3828d80c88c3dd3bf6 100644 (file)
@@ -11,7 +11,8 @@
 macro_rules! arena_types {
     ($macro:path, $tcx:lifetime) => (
         $macro!([
-            [] layouts: rustc_target::abi::Layout,
+            [] layout: rustc_target::abi::Layout,
+            [] fn_abi: rustc_target::abi::call::FnAbi<$tcx, rustc_middle::ty::Ty<$tcx>>,
             // AdtDef are interned and compared by address
             [] adt_def: rustc_middle::ty::AdtDef,
             [] steal_thir: rustc_data_structures::steal::Steal<rustc_middle::thir::Thir<$tcx>>,
index 8476929eaeced2b1d230e5e6f6d964e2e7d2a088..e788dd4be85d715a55bb5c4da496117123861fe6 100644 (file)
@@ -336,7 +336,11 @@ fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
     /// has been removed.
     fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
         if self.kind.can_reconstruct_query_key() {
-            tcx.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
+            Some(
+                tcx.on_disk_cache
+                    .as_ref()?
+                    .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into())),
+            )
         } else {
             None
         }
@@ -385,17 +389,7 @@ fn can_reconstruct_query_key() -> bool {
     }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
-        let hash = tcx.def_path_hash(*self);
-        // If this is a foreign `DefId`, store its current value
-        // in the incremental cache. When we decode the cache,
-        // we will use the old DefIndex as an initial guess for
-        // a lookup into the crate metadata.
-        if !self.is_local() {
-            if let Some(cache) = &tcx.on_disk_cache {
-                cache.store_foreign_def_id_hash(*self, hash);
-            }
-        }
-        hash.0
+        tcx.def_path_hash(*self).0
     }
 
     fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
index aa61219ad789e9f523e3c01bd9abd30453435db9..35dc1631db3c2757094b2e952d7e9a32cb8dabf0 100644 (file)
@@ -92,12 +92,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
     type DepKind = DepKind;
     type StableHashingContext = StableHashingContext<'tcx>;
 
-    fn register_reused_dep_node(&self, dep_node: &DepNode) {
-        if let Some(cache) = self.on_disk_cache.as_ref() {
-            cache.register_reused_dep_node(*self, dep_node)
-        }
-    }
-
+    #[inline]
     fn create_stable_hashing_context(&self) -> Self::StableHashingContext {
         TyCtxt::create_stable_hashing_context(*self)
     }
index be9e38aca65d10feeceb8e1d50b7fb208ef86ea5..f37b976fba68d3d6d450cee0c1cb4b9b353bb2ac 100644 (file)
 
 /// This is the replacement export map. It maps a module to all of the exports
 /// within.
-pub type ExportMap<Id> = FxHashMap<LocalDefId, Vec<Export<Id>>>;
+pub type ExportMap = FxHashMap<LocalDefId, Vec<Export>>;
 
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct Export<Id> {
+pub struct Export {
     /// The name of the target.
     pub ident: Ident,
     /// The resolution of the target.
-    pub res: Res<Id>,
+    /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter.
+    pub res: Res<!>,
     /// The span of the target.
     pub span: Span,
     /// The visibility of the export.
     /// We include non-`pub` exports for hygienic macros that get used from extern crates.
     pub vis: ty::Visibility,
 }
-
-impl<Id> Export<Id> {
-    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
-        Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis }
-    }
-}
index 1351b4950f143cb9714bd4cc95fbe2ca7ba208ee..5ecb1c9b0ffcc3b62cf49b960178704dab9ea131 100644 (file)
@@ -62,13 +62,6 @@ fn hash_body(
     stable_hasher.finish()
 }
 
-/// Represents an entry and its parent `HirId`.
-#[derive(Copy, Clone, Debug)]
-pub struct Entry<'hir> {
-    parent: HirId,
-    node: Node<'hir>,
-}
-
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
@@ -420,18 +413,18 @@ fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
         self.visit_nested_trait_item(id);
     }
 
-    fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) {
+    fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
         // Do not visit the duplicate information in ImplItemRef. We want to
         // map the actual nodes, not the duplicate ones in the *Ref.
-        let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii;
+        let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
 
         self.visit_nested_impl_item(id);
     }
 
-    fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef<'hir>) {
+    fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
         // Do not visit the duplicate information in ForeignItemRef. We want to
         // map the actual nodes, not the duplicate ones in the *Ref.
-        let ForeignItemRef { id, ident: _, span: _, vis: _ } = *fi;
+        let ForeignItemRef { id, ident: _, span: _ } = *fi;
 
         self.visit_nested_foreign_item(id);
     }
index e0b6039fe348f4bd0e24ed5581000ee9dec978b9..3707fadadac208cf774ce2363aa25582d66cd5fd 100644 (file)
@@ -1,13 +1,13 @@
 use self::collector::NodeCollector;
 
-use crate::hir::{AttributeMap, IndexedHir, Owner};
+use crate::hir::{AttributeMap, IndexedHir, ModuleItems, Owner};
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 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_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -19,6 +19,7 @@
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
+use std::collections::VecDeque;
 
 pub mod blocks;
 mod collector;
@@ -82,12 +83,12 @@ pub struct Map<'hir> {
 
 /// An iterator that walks up the ancestor tree of a given `HirId`.
 /// Constructed using `tcx.hir().parent_iter(hir_id)`.
-pub struct ParentHirIterator<'map, 'hir> {
+pub struct ParentHirIterator<'hir> {
     current_id: HirId,
-    map: &'map Map<'hir>,
+    map: Map<'hir>,
 }
 
-impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentHirIterator<'hir> {
     type Item = (HirId, Node<'hir>);
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -114,12 +115,12 @@ fn next(&mut self) -> Option<Self::Item> {
 
 /// An iterator that walks up the ancestor tree of a given `HirId`.
 /// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
-pub struct ParentOwnerIterator<'map, 'hir> {
+pub struct ParentOwnerIterator<'hir> {
     current_id: HirId,
-    map: &'map Map<'hir>,
+    map: Map<'hir>,
 }
 
-impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentOwnerIterator<'hir> {
     type Item = (HirId, OwnerNode<'hir>);
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -206,11 +207,6 @@ pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
     }
 
     pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
-        // FIXME(eddyb) support `find` on the crate root.
-        if local_def_id.to_def_id().index == CRATE_DEF_INDEX {
-            return Some(DefKind::Mod);
-        }
-
         let hir_id = self.local_def_id_to_hir_id(local_def_id);
         let def_kind = match self.find(hir_id)? {
             Node::Item(item) => match item.kind {
@@ -541,32 +537,64 @@ pub fn visit_item_likes_in_module<V>(&self, module: LocalDefId, visitor: &mut V)
     {
         let module = self.tcx.hir_module_items(module);
 
-        for id in &module.items {
+        for id in module.items.iter() {
             visitor.visit_item(self.item(*id));
         }
 
-        for id in &module.trait_items {
+        for id in module.trait_items.iter() {
             visitor.visit_trait_item(self.trait_item(*id));
         }
 
-        for id in &module.impl_items {
+        for id in module.impl_items.iter() {
             visitor.visit_impl_item(self.impl_item(*id));
         }
 
-        for id in &module.foreign_items {
+        for id in module.foreign_items.iter() {
             visitor.visit_foreign_item(self.foreign_item(*id));
         }
     }
 
+    pub fn for_each_module(&self, f: impl Fn(LocalDefId)) {
+        let mut queue = VecDeque::new();
+        queue.push_back(CRATE_DEF_ID);
+
+        while let Some(id) = queue.pop_front() {
+            f(id);
+            let items = self.tcx.hir_module_items(id);
+            queue.extend(items.submodules.iter().copied())
+        }
+    }
+
+    #[cfg(not(parallel_compiler))]
+    #[inline]
+    pub fn par_for_each_module(&self, f: impl Fn(LocalDefId)) {
+        self.for_each_module(f)
+    }
+
+    #[cfg(parallel_compiler)]
+    pub fn par_for_each_module(&self, f: impl Fn(LocalDefId) + Sync) {
+        use rustc_data_structures::sync::{par_iter, ParallelIterator};
+        par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
+
+        fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
+        where
+            F: Fn(LocalDefId) + Sync,
+        {
+            (*f)(module);
+            let items = tcx.hir_module_items(module);
+            par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
+        }
+    }
+
     /// 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> {
+    pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
         ParentHirIterator { current_id, map: self }
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
     /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
-    pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> {
+    pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
         ParentOwnerIterator { current_id, map: self }
     }
 
@@ -969,22 +997,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
         .iter_enumerated()
         .filter_map(|(def_id, hod)| {
             let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
-            let mut hasher = StableHasher::new();
-            hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
-            AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
-                .hash_stable(&mut hcx, &mut hasher);
-            Some((def_path_hash, hasher.finish()))
+            let hash = hod.as_ref()?.hash;
+            Some((def_path_hash, hash, def_id))
         })
         .collect();
     hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
 
-    let node_hashes = hir_body_nodes.iter().fold(
-        Fingerprint::ZERO,
-        |combined_fingerprint, &(def_path_hash, fingerprint)| {
-            combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
-        },
-    );
-
     let upstream_crates = upstream_crates(tcx);
 
     // We hash the final, remapped names of all local source files so we
@@ -1004,7 +1022,17 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     source_file_names.sort_unstable();
 
     let mut stable_hasher = StableHasher::new();
-    node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
+    for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
+        def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
+        fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
+        AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
+            .hash_stable(&mut hcx, &mut stable_hasher);
+        if tcx.sess.opts.debugging_opts.incremental_relative_spans {
+            let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
+            debug_assert_eq!(span.parent(), None);
+            span.hash_stable(&mut hcx, &mut stable_hasher);
+        }
+    }
     upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
@@ -1118,3 +1146,69 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
         None => format!("unknown node{}", id_str),
     }
 }
+
+pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalDefId) -> ModuleItems {
+    let mut collector = ModuleCollector {
+        tcx,
+        submodules: Vec::default(),
+        items: Vec::default(),
+        trait_items: Vec::default(),
+        impl_items: Vec::default(),
+        foreign_items: Vec::default(),
+    };
+
+    let (hir_mod, span, hir_id) = tcx.hir().get_module(module_id);
+    collector.visit_mod(hir_mod, span, hir_id);
+
+    let ModuleCollector { submodules, items, trait_items, impl_items, foreign_items, .. } =
+        collector;
+    return ModuleItems {
+        submodules: submodules.into_boxed_slice(),
+        items: items.into_boxed_slice(),
+        trait_items: trait_items.into_boxed_slice(),
+        impl_items: impl_items.into_boxed_slice(),
+        foreign_items: foreign_items.into_boxed_slice(),
+    };
+
+    struct ModuleCollector<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        submodules: Vec<LocalDefId>,
+        items: Vec<ItemId>,
+        trait_items: Vec<TraitItemId>,
+        impl_items: Vec<ImplItemId>,
+        foreign_items: Vec<ForeignItemId>,
+    }
+
+    impl<'hir> Visitor<'hir> for ModuleCollector<'hir> {
+        type Map = Map<'hir>;
+
+        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
+            intravisit::NestedVisitorMap::All(self.tcx.hir())
+        }
+
+        fn visit_item(&mut self, item: &'hir Item<'hir>) {
+            self.items.push(item.item_id());
+            if let ItemKind::Mod(..) = item.kind {
+                // If this declares another module, do not recurse inside it.
+                self.submodules.push(item.def_id);
+            } else {
+                intravisit::walk_item(self, item)
+            }
+        }
+
+        fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
+            self.trait_items.push(item.trait_item_id());
+            intravisit::walk_trait_item(self, item)
+        }
+
+        fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
+            self.impl_items.push(item.impl_item_id());
+            intravisit::walk_impl_item(self, item)
+        }
+
+        fn visit_foreign_item(&mut self, item: &'hir ForeignItem<'hir>) {
+            self.foreign_items.push(item.foreign_item_id());
+            intravisit::walk_foreign_item(self, item)
+        }
+    }
+}
index 34aee4f1b3b3fc24703738a8be4c59927c4532c0..de4b75f9463c3659a0841aa586bc2ddbbad1db54 100644 (file)
@@ -121,6 +121,17 @@ fn range(&self) -> std::collections::btree_map::Range<'_, rustc_hir::HirId, &[At
     }
 }
 
+/// Gather the LocalDefId for each item-like within a module, including items contained within
+/// bodies.  The Ids are in visitor order.  This is used to partition a pass between modules.
+#[derive(Debug, HashStable)]
+pub struct ModuleItems {
+    submodules: Box<[LocalDefId]>,
+    items: Box<[ItemId]>,
+    trait_items: Box<[TraitItemId]>,
+    impl_items: Box<[ImplItemId]>,
+    foreign_items: Box<[ForeignItemId]>,
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     #[inline(always)]
     pub fn hir(self) -> map::Map<'tcx> {
@@ -140,7 +151,7 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_crate = |tcx, ()| tcx.untracked_crate;
     providers.index_hir = map::index_hir;
     providers.crate_hash = map::crate_hash;
-    providers.hir_module_items = |tcx, id| &tcx.untracked_crate.modules[&id];
+    providers.hir_module_items = map::hir_module_items;
     providers.hir_owner = |tcx, id| {
         let owner = tcx.index_hir(()).map[id].as_ref()?;
         let node = owner.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
@@ -153,6 +164,7 @@ pub fn provide(providers: &mut Providers) {
         index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
     };
     providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
+    providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
     providers.fn_arg_names = |tcx, id| {
         let hir = tcx.hir();
index 32ccdafaeb48c926a87609b2d77ae89564a19b9d..c7f58ce5b13371af578d7ce83203e2d667c36e06 100644 (file)
@@ -12,7 +12,7 @@
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
 
 use smallvec::SmallVec;
 use std::cmp::Ord;
@@ -28,7 +28,6 @@ fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
 /// things (e.g., each `DefId`/`DefPath` is only hashed once).
 #[derive(Clone)]
 pub struct StableHashingContext<'a> {
-    sess: &'a Session,
     definitions: &'a Definitions,
     cstore: &'a dyn CrateStore,
     pub(super) body_resolver: BodyResolver<'a>,
@@ -78,7 +77,6 @@ fn new_with_or_without_spans(
             !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
 
         StableHashingContext {
-            sess,
             body_resolver: BodyResolver(krate),
             definitions,
             cstore,
@@ -229,6 +227,11 @@ fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.def_path_hash(def_id)
     }
 
+    #[inline]
+    fn def_span(&self, def_id: LocalDefId) -> Span {
+        self.definitions.def_span(def_id)
+    }
+
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
index 8e53e4ba948058bdd4351b7a93227ddf27aea74a..3b0640eb98d93fc7035a65983dc4d06fa9dc8c3f 100644 (file)
@@ -90,7 +90,10 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
             ty::ReFree(ref free_region) => {
                 free_region.hash_stable(hcx, hasher);
             }
-            ty::ReVar(..) | ty::RePlaceholder(..) => {
+            ty::RePlaceholder(p) => {
+                p.hash_stable(hcx, hasher);
+            }
+            ty::ReVar(..) => {
                 bug!("StableHasher: unexpected region {:?}", *self)
             }
         }
index 94267ec64c73c0cee5dff4d47263356180564298..02f0294c8ad25e944164e16a9e9bfb971ea568ba 100644 (file)
@@ -33,6 +33,7 @@
 #![feature(discriminant_kind)]
 #![feature(exhaustive_patterns)]
 #![feature(if_let_guard)]
+#![feature(map_first_last)]
 #![feature(never_type)]
 #![feature(extern_types)]
 #![feature(new_uninit)]
index 8150e67929509e3f4df6d2a26758786069e59a95..81c44b27033ec07252961490db2a035e2af1b218 100644 (file)
@@ -199,14 +199,10 @@ pub trait CrateStore: std::fmt::Debug {
     // incr.  comp. uses to identify a CrateNum.
     fn crate_name(&self, cnum: CrateNum) -> Symbol;
     fn stable_crate_id(&self, cnum: CrateNum) -> StableCrateId;
+    fn stable_crate_id_to_crate_num(&self, stable_crate_id: StableCrateId) -> CrateNum;
 
     /// Fetch a DefId from a DefPathHash for a foreign crate.
-    fn def_path_hash_to_def_id(
-        &self,
-        cnum: CrateNum,
-        index_guess: u32,
-        hash: DefPathHash,
-    ) -> Option<DefId>;
+    fn def_path_hash_to_def_id(&self, cnum: CrateNum, hash: DefPathHash) -> DefId;
     fn expn_hash_to_expn_id(&self, cnum: CrateNum, index_guess: u32, hash: ExpnHash) -> ExpnId;
 
     // utility functions
index bd4e83a42ef515c371bdd9ed0aa702b4d228a537..e271f59da87967fe2c8940425ab2798ea08e2291 100644 (file)
@@ -257,7 +257,8 @@ pub struct ScopeTree {
     /// ```
     ///
     /// With the HIR tree (calls numbered for expository purposes)
-    /// ```
+    ///
+    /// ```text
     ///     Call#0(foo, [Call#1(f), Yield(y), Call#2(bar, Call#3(g))])
     /// ```
     ///
diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs
deleted file mode 100644 (file)
index 1ef1024..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-//! A subset of a mir body used for const evaluatability checking.
-use crate::mir::{self, CastKind};
-use crate::ty::{self, Ty};
-
-rustc_index::newtype_index! {
-    /// An index into an `AbstractConst`.
-    pub struct NodeId {
-        derive [HashStable]
-        DEBUG_FORMAT = "n{}",
-    }
-}
-
-/// A node of an `AbstractConst`.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum Node<'tcx> {
-    Leaf(&'tcx ty::Const<'tcx>),
-    Binop(mir::BinOp, NodeId, NodeId),
-    UnaryOp(mir::UnOp, NodeId),
-    FunctionCall(NodeId, &'tcx [NodeId]),
-    Cast(CastKind, NodeId, Ty<'tcx>),
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum NotConstEvaluatable {
-    Error(rustc_errors::ErrorReported),
-    MentionsInfer,
-    MentionsParam,
-}
-
-impl From<rustc_errors::ErrorReported> for NotConstEvaluatable {
-    fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable {
-        NotConstEvaluatable::Error(e)
-    }
-}
-
-TrivialTypeFoldableAndLiftImpls! {
-    NotConstEvaluatable,
-}
index 3eee45a9230d1ffbd68e3d17e55f7e136dc97fbc..c9dc5a0f3b5ec22c3111cbc5198f4f67f85ad823 100644 (file)
@@ -3,7 +3,7 @@
 use rustc_macros::HashStable;
 use rustc_target::abi::{HasDataLayout, Size};
 
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -20,29 +20,27 @@ fn pointer_size(&self) -> Size {
 
     #[inline]
     fn machine_usize_max(&self) -> u64 {
-        let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
-        u64::try_from(max_usize_plus_1 - 1).unwrap()
+        self.pointer_size().unsigned_int_max().try_into().unwrap()
     }
 
     #[inline]
     fn machine_isize_min(&self) -> i64 {
-        let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
-        i64::try_from(-max_isize_plus_1).unwrap()
+        self.pointer_size().signed_int_min().try_into().unwrap()
     }
 
     #[inline]
     fn machine_isize_max(&self) -> i64 {
-        let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
-        i64::try_from(max_isize_plus_1 - 1).unwrap()
+        self.pointer_size().signed_int_max().try_into().unwrap()
     }
 
     #[inline]
     fn machine_usize_to_isize(&self, val: u64) -> i64 {
         let val = val as i64;
-        // Now clamp into the machine_isize range.
+        // Now wrap-around into the machine_isize range.
         if val > self.machine_isize_max() {
             // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
             // i64.
+            debug_assert!(self.pointer_size().bits() < 64);
             let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
             val - i64::try_from(max_usize_plus_1).unwrap()
         } else {
index 38d4c5b4bd10ee208c49cd7bee2b4ca175597434..3e9c02ee268cab9a9e197198ad41c43a5ca13611 100644 (file)
@@ -40,7 +40,6 @@
 use self::predecessors::{PredecessorCache, Predecessors};
 pub use self::query::*;
 
-pub mod abstract_const;
 pub mod coverage;
 mod generic_graph;
 pub mod generic_graphviz;
@@ -993,6 +992,9 @@ pub enum LocalInfo<'tcx> {
     StaticRef { def_id: DefId, is_thread_local: bool },
     /// A temporary created that references the const with the given `DefId`
     ConstRef { def_id: DefId },
+    /// A temporary created during the creation of an aggregate
+    /// (e.g. a temporary for `foo` in `MyStruct { my_field: foo }`)
+    AggregateTemp,
 }
 
 impl<'tcx> LocalDecl<'tcx> {
@@ -1736,7 +1738,7 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Place<'_>, 16);
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -2062,7 +2064,7 @@ pub enum Operand<'tcx> {
     Constant(Box<Constant<'tcx>>),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Operand<'_>, 24);
 
 impl<'tcx> Debug for Operand<'tcx> {
@@ -2200,7 +2202,7 @@ pub enum Rvalue<'tcx> {
     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Rvalue<'_>, 40);
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -2226,7 +2228,7 @@ pub enum AggregateKind<'tcx> {
     Generator(DefId, SubstsRef<'tcx>, hir::Movability),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(AggregateKind<'_>, 48);
 
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -2278,6 +2280,8 @@ pub fn is_checkable(self) -> bool {
 pub enum NullOp {
     /// Returns the size of a value of that type
     SizeOf,
+    /// Returns the minimum alignment of a type
+    AlignOf,
     /// Creates a new uninitialized box for a value of that type
     Box,
 }
index 1bdb6ca012b4aa6bdd63b34a7968425d8d472aa5..b003a504691bbce1f8279209f4e447ed7da449cd 100644 (file)
@@ -1,6 +1,6 @@
 //! Values computed by queries that use MIR.
 
-use crate::mir::{abstract_const, Body, Promoted};
+use crate::mir::{Body, Promoted};
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
@@ -332,17 +332,15 @@ pub enum ConstraintCategory {
     CopyBound,
     SizedBound,
     Assignment,
+    /// A constraint that came from a usage of a variable (e.g. in an ADT expression
+    /// like `Foo { field: my_val }`)
+    Usage,
     OpaqueType,
     ClosureUpvar(hir::HirId),
 
     /// A "boring" constraint (caused by the given location) is one that
     /// the user probably doesn't want to see described in diagnostics,
     /// because it is kind of an artifact of the type system setup.
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
     Boring,
     // Boring and applicable everywhere.
     BoringNoLocation,
@@ -431,16 +429,4 @@ pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'
             self.mir_for_ctfe(def.did)
         }
     }
-
-    #[inline]
-    pub fn mir_abstract_const_opt_const_arg(
-        self,
-        def: ty::WithOptConstParam<DefId>,
-    ) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> {
-        if let Some((did, param_did)) = def.as_const_arg() {
-            self.mir_abstract_const_of_const_arg((did, param_did))
-        } else {
-            self.mir_abstract_const(def.did)
-        }
-    }
 }
index 74d303cee5d1efc14c6689cecde1a9c651cb857d..b48e8a868efdb1cf01a0b9e9abf5cf93fbbad603 100644 (file)
@@ -196,7 +196,7 @@ pub fn ty<D>(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'tcx>
             Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
             Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
             Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
-            Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
index c93996162e3e372b491ce58f55d3927a39fe67d2..c13d7720e37540747236a788225c4549d70fb6bc 100644 (file)
         desc { "get the resolver outputs" }
     }
 
+    /// Return the span for a definition.
+    /// Contrary to `def_span` below, this query returns the full absolute span of the definition.
+    /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
+    /// of rustc_middle::hir::source_map.
+    query source_span(key: LocalDefId) -> Span {
+        desc { "get the source span" }
+    }
+
     /// Represents crate as a whole (as distinct from the top-level crate module).
     /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
     /// we will have to assume that any change means that you need to be recompiled.
@@ -44,8 +52,8 @@
     ///
     /// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
     /// Avoid calling this query directly.
-    query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems {
-        eval_always
+    query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
+        storage(ArenaCacheSelector<'tcx>)
         desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
     }
 
     /// Try to build an abstract representation of the given constant.
-    query mir_abstract_const(
+    query thir_abstract_const(
         key: DefId
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         desc {
             |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
         }
     }
     /// Try to build an abstract representation of the given constant.
-    query mir_abstract_const_of_const_arg(
+    query thir_abstract_const_of_const_arg(
         key: (LocalDefId, DefId)
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         desc {
             |tcx|
             "building an abstract representation for the const argument {}",
         desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a const `impl`. **Do not call this function manually.**
-    ///
-    /// This query caches the base data for the `is_const_impl` helper function, which also
-    /// takes into account stability attributes (e.g., `#[rustc_const_unstable]`).
-    query is_const_impl_raw(key: DefId) -> bool {
-        desc { |tcx| "checking if item is const impl: `{}`", tcx.def_path_str(key) }
-    }
-
     query asyncness(key: DefId) -> hir::IsAsync {
         desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
     }
         desc { "computing layout of `{}`", key.value }
     }
 
+    /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
+    ///
+    /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
+    /// instead, where the instance is an `InstanceDef::Virtual`.
+    query fn_abi_of_fn_ptr(
+        key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+        desc { "computing call ABI of `{}` function pointers", key.value.0 }
+    }
+
+    /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
+    /// direct calls to an `fn`.
+    ///
+    /// NB: that includes virtual calls, which are represented by "direct calls"
+    /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+    query fn_abi_of_instance(
+        key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>
+    ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> {
+        desc { "computing call ABI of `{}`", key.value.0 }
+    }
+
     query dylib_dependency_formats(_: CrateNum)
                                     -> &'tcx [(CrateNum, LinkagePreference)] {
         desc { "dylib dependency formats of crate" }
         fatal_cycle
         desc { "query a crate's configured panic strategy" }
     }
+    query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
+        fatal_cycle
+        desc { "query a crate's configured panic-in-drop strategy" }
+    }
     query is_no_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "test whether a crate has `#![no_builtins]`" }
         desc { "traits in scope at a block" }
     }
 
-    query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export<LocalDefId>]> {
+    query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> {
         desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
         eval_always
         desc { "fetching what a crate is named" }
     }
-    query item_children(def_id: DefId) -> &'tcx [Export<hir::HirId>] {
+    query item_children(def_id: DefId) -> &'tcx [Export] {
         desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
index 91a64e163e7c0172efd2cb58395ed574cd96402b..8d6fd1e729d3b52b5e4ec75dc6bd775317101924 100644 (file)
@@ -33,6 +33,9 @@
 use std::fmt;
 use std::ops::Index;
 
+pub mod abstract_const;
+pub mod visit;
+
 newtype_index! {
     /// An index to an [`Arm`] stored in [`Thir::arms`]
     #[derive(HashStable)]
diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs
new file mode 100644 (file)
index 0000000..f80bead
--- /dev/null
@@ -0,0 +1,61 @@
+//! A subset of a mir body used for const evaluatability checking.
+use crate::mir;
+use crate::ty::{self, Ty, TyCtxt};
+use rustc_errors::ErrorReported;
+
+rustc_index::newtype_index! {
+    /// An index into an `AbstractConst`.
+    pub struct NodeId {
+        derive [HashStable]
+        DEBUG_FORMAT = "n{}",
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum CastKind {
+    /// thir::ExprKind::As
+    As,
+    /// thir::ExprKind::Use
+    Use,
+}
+
+/// A node of an `AbstractConst`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum Node<'tcx> {
+    Leaf(&'tcx ty::Const<'tcx>),
+    Binop(mir::BinOp, NodeId, NodeId),
+    UnaryOp(mir::UnOp, NodeId),
+    FunctionCall(NodeId, &'tcx [NodeId]),
+    Cast(CastKind, NodeId, Ty<'tcx>),
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum NotConstEvaluatable {
+    Error(ErrorReported),
+    MentionsInfer,
+    MentionsParam,
+}
+
+impl From<ErrorReported> for NotConstEvaluatable {
+    fn from(e: ErrorReported) -> NotConstEvaluatable {
+        NotConstEvaluatable::Error(e)
+    }
+}
+
+TrivialTypeFoldableAndLiftImpls! {
+    NotConstEvaluatable,
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    #[inline]
+    pub fn thir_abstract_const_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<rustc_hir::def_id::DefId>,
+    ) -> Result<Option<&'tcx [Node<'tcx>]>, ErrorReported> {
+        if let Some((did, param_did)) = def.as_const_arg() {
+            self.thir_abstract_const_of_const_arg((did, param_did))
+        } else {
+            self.thir_abstract_const(def.did)
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
new file mode 100644 (file)
index 0000000..7fc15e0
--- /dev/null
@@ -0,0 +1,242 @@
+use super::{
+    Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
+};
+use rustc_middle::ty::Const;
+
+pub trait Visitor<'a, 'tcx: 'a>: Sized {
+    fn thir(&self) -> &'a Thir<'tcx>;
+
+    fn visit_expr(&mut self, expr: &Expr<'tcx>) {
+        walk_expr(self, expr);
+    }
+
+    fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
+        walk_stmt(self, stmt);
+    }
+
+    fn visit_block(&mut self, block: &Block) {
+        walk_block(self, block);
+    }
+
+    fn visit_arm(&mut self, arm: &Arm<'tcx>) {
+        walk_arm(self, arm);
+    }
+
+    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+        walk_pat(self, pat);
+    }
+
+    fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
+}
+
+pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
+    use ExprKind::*;
+    match expr.kind {
+        Scope { value, region_scope: _, lint_level: _ } => {
+            visitor.visit_expr(&visitor.thir()[value])
+        }
+        Box { value } => visitor.visit_expr(&visitor.thir()[value]),
+        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 {
+                visitor.visit_expr(&visitor.thir()[else_expr]);
+            }
+        }
+        Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
+            visitor.visit_expr(&visitor.thir()[fun]);
+            for &arg in &**args {
+                visitor.visit_expr(&visitor.thir()[arg]);
+            }
+        }
+        Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
+        Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
+            visitor.visit_expr(&visitor.thir()[lhs]);
+            visitor.visit_expr(&visitor.thir()[rhs]);
+        }
+        Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+        Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
+        Use { source } => visitor.visit_expr(&visitor.thir()[source]),
+        NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
+        Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
+        Let { expr, .. } => {
+            visitor.visit_expr(&visitor.thir()[expr]);
+        }
+        Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
+        Match { scrutinee, ref arms } => {
+            visitor.visit_expr(&visitor.thir()[scrutinee]);
+            for &arm in &**arms {
+                visitor.visit_arm(&visitor.thir()[arm]);
+            }
+        }
+        Block { ref body } => visitor.visit_block(body),
+        Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
+            visitor.visit_expr(&visitor.thir()[lhs]);
+            visitor.visit_expr(&visitor.thir()[rhs]);
+        }
+        Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
+        Index { lhs, index } => {
+            visitor.visit_expr(&visitor.thir()[lhs]);
+            visitor.visit_expr(&visitor.thir()[index]);
+        }
+        VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
+        Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+        AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
+        Break { value, label: _ } => {
+            if let Some(value) = value {
+                visitor.visit_expr(&visitor.thir()[value])
+            }
+        }
+        Continue { label: _ } => {}
+        Return { value } => {
+            if let Some(value) = value {
+                visitor.visit_expr(&visitor.thir()[value])
+            }
+        }
+        ConstBlock { value } => visitor.visit_const(value),
+        Repeat { value, count } => {
+            visitor.visit_expr(&visitor.thir()[value]);
+            visitor.visit_const(count);
+        }
+        Array { ref fields } | Tuple { ref fields } => {
+            for &field in &**fields {
+                visitor.visit_expr(&visitor.thir()[field]);
+            }
+        }
+        Adt(box crate::thir::Adt {
+            ref fields,
+            ref base,
+            adt_def: _,
+            variant_index: _,
+            substs: _,
+            user_ty: _,
+        }) => {
+            for field in &**fields {
+                visitor.visit_expr(&visitor.thir()[field.expr]);
+            }
+            if let Some(base) = base {
+                visitor.visit_expr(&visitor.thir()[base.base]);
+            }
+        }
+        PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
+            visitor.visit_expr(&visitor.thir()[source])
+        }
+        Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
+        Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
+        StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
+        InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
+            for op in &**operands {
+                use InlineAsmOperand::*;
+                match op {
+                    In { expr, reg: _ }
+                    | Out { expr: Some(expr), reg: _, late: _ }
+                    | InOut { expr, reg: _, late: _ }
+                    | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
+                    SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
+                        visitor.visit_expr(&visitor.thir()[*in_expr]);
+                        if let Some(out_expr) = out_expr {
+                            visitor.visit_expr(&visitor.thir()[*out_expr]);
+                        }
+                    }
+                    Out { expr: None, reg: _, late: _ }
+                    | Const { value: _, span: _ }
+                    | SymStatic { def_id: _ } => {}
+                }
+            }
+        }
+        ThreadLocalRef(_) => {}
+        LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
+            for &out_expr in &**outputs {
+                visitor.visit_expr(&visitor.thir()[out_expr]);
+            }
+            for &in_expr in &**inputs {
+                visitor.visit_expr(&visitor.thir()[in_expr]);
+            }
+        }
+        Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
+    }
+}
+
+pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
+    match &stmt.kind {
+        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
+        StmtKind::Let {
+            initializer,
+            remainder_scope: _,
+            init_scope: _,
+            ref pattern,
+            lint_level: _,
+        } => {
+            if let Some(init) = initializer {
+                visitor.visit_expr(&visitor.thir()[*init]);
+            }
+            visitor.visit_pat(pattern);
+        }
+    }
+}
+
+pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
+    for &stmt in &*block.stmts {
+        visitor.visit_stmt(&visitor.thir()[stmt]);
+    }
+    if let Some(expr) = block.expr {
+        visitor.visit_expr(&visitor.thir()[expr]);
+    }
+}
+
+pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
+    match arm.guard {
+        Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
+        Some(Guard::IfLet(ref pat, expr)) => {
+            visitor.visit_pat(pat);
+            visitor.visit_expr(&visitor.thir()[expr]);
+        }
+        None => {}
+    }
+    visitor.visit_pat(&arm.pattern);
+    visitor.visit_expr(&visitor.thir()[arm.body]);
+}
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+    use PatKind::*;
+    match pat.kind.as_ref() {
+        AscribeUserType { subpattern, ascription: _ }
+        | Deref { subpattern }
+        | Binding {
+            subpattern: Some(subpattern),
+            mutability: _,
+            mode: _,
+            var: _,
+            ty: _,
+            is_primary: _,
+            name: _,
+        } => visitor.visit_pat(&subpattern),
+        Binding { .. } | Wild => {}
+        Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+            for subpattern in subpatterns {
+                visitor.visit_pat(&subpattern.pattern);
+            }
+        }
+        Constant { value } => visitor.visit_const(value),
+        Range(range) => {
+            visitor.visit_const(range.lo);
+            visitor.visit_const(range.hi);
+        }
+        Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+            for subpattern in prefix {
+                visitor.visit_pat(&subpattern);
+            }
+            if let Some(pat) = slice {
+                visitor.visit_pat(pat);
+            }
+            for subpattern in suffix {
+                visitor.visit_pat(&subpattern);
+            }
+        }
+        Or { pats } => {
+            for pat in pats {
+                visitor.visit_pat(&pat);
+            }
+        }
+    };
+}
index 74edb17fe32f1af9e4daccc8c1ab447c412893e8..88a7722c9ccf08bd0ff4437962db68e57f49cca3 100644 (file)
@@ -9,7 +9,7 @@
 mod structural_impls;
 
 use crate::infer::canonical::Canonical;
-use crate::mir::abstract_const::NotConstEvaluatable;
+use crate::thir::abstract_const::NotConstEvaluatable;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, AdtKind, Ty, TyCtxt};
 
@@ -253,6 +253,15 @@ pub enum ObligationCauseCode<'tcx> {
 
     DerivedObligation(DerivedObligationCause<'tcx>),
 
+    FunctionArgumentObligation {
+        /// The node of the relevant argument in the function call.
+        arg_hir_id: hir::HirId,
+        /// The node of the function call.
+        call_hir_id: hir::HirId,
+        /// The obligation introduced by this argument.
+        parent_code: Lrc<ObligationCauseCode<'tcx>>,
+    },
+
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplConstObligation,
 
@@ -340,7 +349,7 @@ pub enum ObligationCauseCode<'tcx> {
     WellFormed(Option<WellFormedLoc>),
 
     /// From `match_impl`. The cause for us having to match an impl, and the DefId we are matching against.
-    MatchImpl(Lrc<ObligationCauseCode<'tcx>>, DefId),
+    MatchImpl(ObligationCause<'tcx>, DefId),
 }
 
 /// The 'location' at which we try to perform HIR-based wf checking.
@@ -368,11 +377,12 @@ impl ObligationCauseCode<'_> {
     // Return the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
         let mut base_cause = self;
-        while let BuiltinDerivedObligation(cause)
-        | ImplDerivedObligation(cause)
-        | DerivedObligation(cause) = base_cause
+        while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
+        | ImplDerivedObligation(DerivedObligationCause { parent_code, .. })
+        | DerivedObligation(DerivedObligationCause { parent_code, .. })
+        | FunctionArgumentObligation { parent_code, .. } = base_cause
         {
-            base_cause = &cause.parent_code;
+            base_cause = &parent_code;
         }
         base_cause
     }
@@ -529,6 +539,9 @@ pub enum ImplSource<'tcx, N> {
 
     /// ImplSource for a trait alias.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
+
+    /// ImplSource for a `const Drop` implementation.
+    ConstDrop(ImplSourceConstDropData),
 }
 
 impl<'tcx, N> ImplSource<'tcx, N> {
@@ -543,7 +556,8 @@ pub fn nested_obligations(self) -> Vec<N> {
             ImplSource::Object(d) => d.nested,
             ImplSource::FnPointer(d) => d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
-            | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
+            | ImplSource::Pointee(ImplSourcePointeeData)
+            | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(),
             ImplSource::TraitAlias(d) => d.nested,
             ImplSource::TraitUpcasting(d) => d.nested,
         }
@@ -560,7 +574,8 @@ pub fn borrow_nested_obligations(&self) -> &[N] {
             ImplSource::Object(d) => &d.nested[..],
             ImplSource::FnPointer(d) => &d.nested[..],
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
-            | ImplSource::Pointee(ImplSourcePointeeData) => &[],
+            | ImplSource::Pointee(ImplSourcePointeeData)
+            | ImplSource::ConstDrop(ImplSourceConstDropData) => &[],
             ImplSource::TraitAlias(d) => &d.nested[..],
             ImplSource::TraitUpcasting(d) => &d.nested[..],
         }
@@ -621,6 +636,9 @@ pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
                     nested: d.nested.into_iter().map(f).collect(),
                 })
             }
+            ImplSource::ConstDrop(ImplSourceConstDropData) => {
+                ImplSource::ConstDrop(ImplSourceConstDropData)
+            }
         }
     }
 }
@@ -712,6 +730,9 @@ pub struct ImplSourceFnPointerData<'tcx, N> {
 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub struct ImplSourcePointeeData;
 
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
+pub struct ImplSourceConstDropData;
+
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub alias_def_id: DefId,
@@ -719,7 +740,7 @@ pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum ObjectSafetyViolation {
     /// `Self: Sized` declared on the trait.
     SizedSelf(SmallVec<[Span; 1]>),
@@ -868,7 +889,7 @@ trait objects",
 }
 
 /// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum MethodViolationCode {
     /// e.g., `fn foo()`
     StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
index 62996bf4cbef20cbabd6ac505afbde0533ad811b..3c0fedb360827ef9a0900f384afee996e3407ccf 100644 (file)
@@ -143,6 +143,9 @@ pub enum SelectionCandidate<'tcx> {
     BuiltinObjectCandidate,
 
     BuiltinUnsizeCandidate,
+
+    /// Implementation of `const Drop`.
+    ConstDropCandidate,
 }
 
 /// The result of trait evaluation. The order is important
index aa16e14fedcde9318c9a43bb29a75310b7de5da3..6032004e6077652a408506098dad933be5ba54d4 100644 (file)
@@ -32,6 +32,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
 
             super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
+
+            super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d),
         }
     }
 }
@@ -125,4 +127,5 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     super::IfExpressionCause,
     super::ImplSourceDiscriminantKindData,
     super::ImplSourcePointeeData,
+    super::ImplSourceConstDropData,
 }
index 27927bcca72b7a6accc5a017c64f2ee5c68d0417..c32f0ea9ca55a2c147c9177071379f92960b6a92 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorReported;
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
@@ -288,6 +289,10 @@ pub fn has_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
         self.destructor(tcx).is_some()
     }
 
+    pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
+        matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. }))
+    }
+
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
         assert!(self.is_struct() || self.is_union());
index 4edb6a327b0352f60fd61f148e8e491ee8507600..8b70692960df9374645d95e5ab188486c04a26db 100644 (file)
@@ -12,6 +12,7 @@
     self,
     interpret::{AllocId, Allocation},
 };
+use crate::thir;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
@@ -362,7 +363,7 @@ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] {
     fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
         Ok(decoder.tcx().arena.alloc_from_iter(
             (0..decoder.read_usize()?)
@@ -372,7 +373,7 @@ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] {
     fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
         Ok(decoder.tcx().arena.alloc_from_iter(
             (0..decoder.read_usize()?)
index 1f5057d1da22ff9c73bc66f79eb2f13b919ed801..72b8d7cce7142d93c7ee5e7c9a09c57ee72362ae 100644 (file)
@@ -1,7 +1,7 @@
 //! Type context book-keeping.
 
 use crate::arena::Arena;
-use crate::dep_graph::{DepGraph, DepNode};
+use crate::dep_graph::DepGraph;
 use crate::hir::place::Place as HirPlace;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
@@ -83,23 +83,7 @@ fn new_empty(source_map: &'tcx SourceMap) -> Self
     /// Converts a `DefPathHash` to its corresponding `DefId` in the current compilation
     /// session, if it still exists. This is used during incremental compilation to
     /// turn a deserialized `DefPathHash` into its current `DefId`.
-    fn def_path_hash_to_def_id(
-        &self,
-        tcx: TyCtxt<'tcx>,
-        def_path_hash: DefPathHash,
-    ) -> Option<DefId>;
-
-    /// If the given `dep_node`'s hash still exists in the current compilation,
-    /// and its current `DefId` is foreign, calls `store_foreign_def_id` with it.
-    ///
-    /// Normally, `store_foreign_def_id_hash` can be called directly by
-    /// the dependency graph when we construct a `DepNode`. However,
-    /// when we re-use a deserialized `DepNode` from the previous compilation
-    /// session, we only have the `DefPathHash` available. This method is used
-    /// to that any `DepNode` that we re-use has a `DefPathHash` -> `RawId` written
-    /// out for usage in the next compilation session.
-    fn register_reused_dep_node(&self, tcx: TyCtxt<'tcx>, dep_node: &DepNode);
-    fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash);
+    fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, def_path_hash: DefPathHash) -> DefId;
 
     fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>);
 
@@ -118,8 +102,8 @@ pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc. are allocated from.
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 
-    /// Specifically use a speedy hash algorithm for these hash sets, since
-    /// they're accessed quite often.
+    // Specifically use a speedy hash algorithm for these hash sets, since
+    // they're accessed quite often.
     type_: InternedSet<'tcx, TyS<'tcx>>,
     type_list: InternedSet<'tcx, List<Ty<'tcx>>>,
     substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
@@ -132,9 +116,9 @@ pub struct CtxtInterners<'tcx> {
     projs: InternedSet<'tcx, List<ProjectionKind>>,
     place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
     const_: InternedSet<'tcx, Const<'tcx>>,
-    /// Const allocations.
-    allocation: InternedSet<'tcx, Allocation>,
+    const_allocation: InternedSet<'tcx, Allocation>,
     bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
+    layout: InternedSet<'tcx, Layout>,
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
@@ -152,8 +136,9 @@ fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
             projs: Default::default(),
             place_elems: Default::default(),
             const_: Default::default(),
-            allocation: Default::default(),
+            const_allocation: Default::default(),
             bound_variable_kinds: Default::default(),
+            layout: Default::default(),
         }
     }
 
@@ -1062,10 +1047,9 @@ pub struct GlobalCtxt<'tcx> {
     /// Stores memory for globals (statics/consts).
     pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>,
 
-    layout_interner: ShardedHashMap<&'tcx Layout, ()>,
-
     output_filenames: Arc<OutputFilenames>,
 
+    // FIXME(eddyb) this doesn't belong here and should be using a query.
     pub(super) vtables_cache:
         Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
 }
@@ -1107,13 +1091,6 @@ pub fn alloc_adt_def(
         self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr))
     }
 
-    pub fn intern_const_alloc(self, alloc: Allocation) -> &'tcx Allocation {
-        self.interners
-            .allocation
-            .intern(alloc, |alloc| Interned(self.interners.arena.alloc(alloc)))
-            .0
-    }
-
     /// Allocates a read-only byte or string literal for `mir::interpret`.
     pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
         // Create an allocation that just contains these bytes.
@@ -1122,20 +1099,19 @@ pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
         self.create_memory_alloc(alloc)
     }
 
+    // FIXME(eddyb) move to `direct_interners!`.
     pub fn intern_stability(self, stab: attr::Stability) -> &'tcx attr::Stability {
         self.stability_interner.intern(stab, |stab| self.arena.alloc(stab))
     }
 
+    // FIXME(eddyb) move to `direct_interners!`.
     pub fn intern_const_stability(self, stab: attr::ConstStability) -> &'tcx attr::ConstStability {
         self.const_stability_interner.intern(stab, |stab| self.arena.alloc(stab))
     }
 
-    pub fn intern_layout(self, layout: Layout) -> &'tcx Layout {
-        self.layout_interner.intern(layout, |layout| self.arena.alloc(layout))
-    }
-
     /// Returns a range of the start/end indices specified with the
     /// `rustc_layout_scalar_valid_range` attribute.
+    // FIXME(eddyb) this is an awkward spot for this method, maybe move it?
     pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
         let attrs = self.get_attrs(def_id);
         let get = |name| {
@@ -1210,7 +1186,6 @@ pub fn create_global_ctxt(
             evaluation_cache: Default::default(),
             crate_name: Symbol::intern(crate_name),
             data_layout,
-            layout_interner: Default::default(),
             stability_interner: Default::default(),
             const_stability_interner: Default::default(),
             alloc_map: Lock::new(interpret::AllocMap::new()),
@@ -1316,6 +1291,17 @@ pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId {
         }
     }
 
+    /// Maps a StableCrateId to the corresponding CrateNum. This method assumes
+    /// that the crate in question has already been loaded by the CrateStore.
+    #[inline]
+    pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum {
+        if stable_crate_id == self.sess.local_stable_crate_id() {
+            LOCAL_CRATE
+        } else {
+            self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+        }
+    }
+
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
         // crate name and stable crate id since this code is called from debug!()
@@ -1670,7 +1656,7 @@ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 nop_lift! {type_; Ty<'a> => Ty<'tcx>}
 nop_lift! {region; Region<'a> => Region<'tcx>}
 nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
-nop_lift! {allocation; &'a Allocation => &'tcx Allocation}
+nop_lift! {const_allocation; &'a Allocation => &'tcx Allocation}
 nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
 
 nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
@@ -1962,8 +1948,12 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                     "Const Stability interner: #{}",
                     self.0.const_stability_interner.len()
                 )?;
-                writeln!(fmt, "Allocation interner: #{}", self.0.interners.allocation.len())?;
-                writeln!(fmt, "Layout interner: #{}", self.0.layout_interner.len())?;
+                writeln!(
+                    fmt,
+                    "Const Allocation interner: #{}",
+                    self.0.interners.const_allocation.len()
+                )?;
+                writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?;
 
                 Ok(())
             }
@@ -2051,38 +2041,6 @@ fn borrow<'a>(&'a self) -> &'a [T] {
     }
 }
 
-impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
-    fn borrow(&self) -> &RegionKind {
-        &self.0
-    }
-}
-
-impl<'tcx> Borrow<Const<'tcx>> for Interned<'tcx, Const<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a Const<'tcx> {
-        &self.0
-    }
-}
-
-impl<'tcx> Borrow<Allocation> for Interned<'tcx, Allocation> {
-    fn borrow<'a>(&'a self) -> &'a Allocation {
-        &self.0
-    }
-}
-
-impl<'tcx> PartialEq for Interned<'tcx, Allocation> {
-    fn eq(&self, other: &Self) -> bool {
-        self.0 == other.0
-    }
-}
-
-impl<'tcx> Eq for Interned<'tcx, Allocation> {}
-
-impl<'tcx> Hash for Interned<'tcx, Allocation> {
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        self.0.hash(s)
-    }
-}
-
 macro_rules! direct_interners {
     ($($name:ident: $method:ident($ty:ty),)+) => {
         $(impl<'tcx> PartialEq for Interned<'tcx, $ty> {
@@ -2099,9 +2057,15 @@ fn hash<H: Hasher>(&self, s: &mut H) {
             }
         }
 
+        impl<'tcx> Borrow<$ty> for Interned<'tcx, $ty> {
+            fn borrow<'a>(&'a self) -> &'a $ty {
+                &self.0
+            }
+        }
+
         impl<'tcx> TyCtxt<'tcx> {
             pub fn $method(self, v: $ty) -> &'tcx $ty {
-                self.interners.$name.intern_ref(&v, || {
+                self.interners.$name.intern(v, |v| {
                     Interned(self.interners.arena.alloc(v))
                 }).0
             }
@@ -2112,6 +2076,8 @@ pub fn $method(self, v: $ty) -> &'tcx $ty {
 direct_interners! {
     region: mk_region(RegionKind),
     const_: mk_const(Const<'tcx>),
+    const_allocation: intern_const_alloc(Allocation),
+    layout: intern_layout(Layout),
 }
 
 macro_rules! slice_interners {
index 796ca650bdd77f55bd1f7c6df12175c39a300904..08b4d3aecda0ae358abcd76529f8497010ce8069 100644 (file)
@@ -964,7 +964,7 @@ fn constrain_associated_type_structured_suggestion(
         {
             let (span, sugg) = if has_params {
                 let pos = span.hi() - BytePos(1);
-                let span = Span::new(pos, pos, span.ctxt());
+                let span = Span::new(pos, pos, span.ctxt(), span.parent());
                 (span, format!(", {} = {}", assoc.ident, ty))
             } else {
                 let item_args = self.format_generic_args(assoc_substs);
index f7ab9dd82ac738971450a43ea912ba456ea56a8e..cfbbec374a172acc35fa6d9adf7cc97cd15755db 100644 (file)
@@ -1,4 +1,3 @@
-use crate::ich::StableHashingContext;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
 use crate::ty::subst::Subst;
@@ -6,7 +5,6 @@
 
 use rustc_ast as ast;
 use rustc_attr as attr;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::BitSet;
     ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
 };
 use rustc_target::abi::*;
-use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy};
+use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
 
 use std::cmp;
 use std::fmt;
 use std::iter;
-use std::mem;
 use std::num::NonZeroUsize;
 use std::ops::Bound;
 
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers =
+        ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+}
+
 pub trait IntegerExt {
     fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
     fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
@@ -191,7 +193,7 @@ fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
 pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
 
-#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
     SizeOverflow(Ty<'tcx>),
@@ -248,10 +250,6 @@ fn layout_of<'tcx>(
     })
 }
 
-pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { layout_of, ..*providers };
-}
-
 pub struct LayoutCx<'tcx, C> {
     pub tcx: C,
     pub param_env: ty::ParamEnv<'tcx>,
@@ -290,9 +288,9 @@ fn scalar_pair(&self, a: Scalar, b: Scalar) -> Layout {
 
         // HACK(nox): We iter on `b` and then `a` because `max_by_key`
         // returns the last maximum.
-        let largest_niche = Niche::from_scalar(dl, b_offset, b.clone())
+        let largest_niche = Niche::from_scalar(dl, b_offset, b)
             .into_iter()
-            .chain(Niche::from_scalar(dl, Size::ZERO, a.clone()))
+            .chain(Niche::from_scalar(dl, Size::ZERO, a))
             .max_by_key(|niche| niche.available(dl));
 
         Layout {
@@ -401,7 +399,7 @@ fn univariant_uninterned(
             offsets[i as usize] = offset;
 
             if !repr.hide_niche() {
-                if let Some(mut niche) = field.largest_niche.clone() {
+                if let Some(mut niche) = field.largest_niche {
                     let available = niche.available(dl);
                     if available > largest_niche_available {
                         largest_niche_available = available;
@@ -449,12 +447,12 @@ fn univariant_uninterned(
                             // For plain scalars, or vectors of them, we can't unpack
                             // newtypes for `#[repr(C)]`, as that affects C ABIs.
                             Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
-                                abi = field.abi.clone();
+                                abi = field.abi;
                             }
                             // But scalar pairs are Rust-specific and get
                             // treated as aggregates by C ABIs anyway.
                             Abi::ScalarPair(..) => {
-                                abi = field.abi.clone();
+                                abi = field.abi;
                             }
                             _ => {}
                         }
@@ -463,14 +461,14 @@ fn univariant_uninterned(
 
                 // Two non-ZST fields, and they're both scalars.
                 (
-                    Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref a), .. }, .. })),
-                    Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref b), .. }, .. })),
+                    Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })),
+                    Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })),
                     None,
                 ) => {
                     // Order by the memory placement, not source order.
                     let ((i, a), (j, b)) =
                         if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) };
-                    let pair = self.scalar_pair(a.clone(), b.clone());
+                    let pair = self.scalar_pair(a, b);
                     let pair_offsets = match pair.fields {
                         FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                             assert_eq!(memory_index, &[0, 1]);
@@ -512,9 +510,9 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
         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: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } }
+            let size = value.size(dl);
+            assert!(size.bits() <= 128);
+            Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
         };
         let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
 
@@ -609,7 +607,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         Abi::Aggregate { sized: true }
                     };
 
-                let largest_niche = if count != 0 { element.largest_niche.clone() } else { None };
+                let largest_niche = if count != 0 { element.largest_niche } else { None };
 
                 tcx.intern_layout(Layout {
                     variants: Variants::Single { index: VariantIdx::new(0) },
@@ -768,8 +766,8 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
 
                 // Compute the ABI of the element type:
                 let e_ly = self.layout_of(e_ty)?;
-                let e_abi = if let Abi::Scalar(ref scalar) = e_ly.abi {
-                    scalar.clone()
+                let e_abi = if let Abi::Scalar(scalar) = e_ly.abi {
+                    scalar
                 } else {
                     // This error isn't caught in typeck, e.g., if
                     // the element type of the vector is generic.
@@ -796,7 +794,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields,
                     abi: Abi::Vector { element: e_abi, count: e_len },
-                    largest_niche: e_ly.largest_niche.clone(),
+                    largest_niche: e_ly.largest_niche,
                     size,
                     align,
                 })
@@ -843,13 +841,13 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         // If all non-ZST fields have the same ABI, forward this ABI
                         if optimize && !field.is_zst() {
                             // Normalize scalar_unit to the maximal valid range
-                            let field_abi = match &field.abi {
+                            let field_abi = match field.abi {
                                 Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
                                 Abi::ScalarPair(x, y) => {
                                     Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value))
                                 }
                                 Abi::Vector { element: x, count } => {
-                                    Abi::Vector { element: scalar_unit(x.value), count: *count }
+                                    Abi::Vector { element: scalar_unit(x.value), count }
                                 }
                                 Abi::Uninhabited | Abi::Aggregate { .. } => {
                                     Abi::Aggregate { sized: true }
@@ -970,7 +968,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                                 Niche::from_scalar(dl, Size::ZERO, scalar.clone())
                             };
                             if let Some(niche) = niche {
-                                match &st.largest_niche {
+                                match st.largest_niche {
                                     Some(largest_niche) => {
                                         // Replace the existing niche even if they're equal,
                                         // because this one is at a lower offset.
@@ -1045,7 +1043,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         let niche_candidate = variants[i]
                             .iter()
                             .enumerate()
-                            .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?)))
+                            .filter_map(|(j, field)| Some((j, field.largest_niche?)))
                             .max_by_key(|(_, niche)| niche.available(dl));
 
                         if let Some((field_index, niche, (niche_start, niche_scalar))) =
@@ -1078,31 +1076,24 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                                 Abi::Uninhabited
                             } else {
                                 match st[i].abi {
-                                    Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()),
-                                    Abi::ScalarPair(ref first, ref second) => {
+                                    Abi::Scalar(_) => Abi::Scalar(niche_scalar),
+                                    Abi::ScalarPair(first, second) => {
                                         // We need to use scalar_unit to reset the
                                         // valid range to the maximal one for that
                                         // primitive, because only the niche is
                                         // guaranteed to be initialised, not the
                                         // other primitive.
                                         if offset.bytes() == 0 {
-                                            Abi::ScalarPair(
-                                                niche_scalar.clone(),
-                                                scalar_unit(second.value),
-                                            )
+                                            Abi::ScalarPair(niche_scalar, scalar_unit(second.value))
                                         } else {
-                                            Abi::ScalarPair(
-                                                scalar_unit(first.value),
-                                                niche_scalar.clone(),
-                                            )
+                                            Abi::ScalarPair(scalar_unit(first.value), niche_scalar)
                                         }
                                     }
                                     _ => Abi::Aggregate { sized: true },
                                 }
                             };
 
-                            let largest_niche =
-                                Niche::from_scalar(dl, offset, niche_scalar.clone());
+                            let largest_niche = Niche::from_scalar(dl, offset, niche_scalar);
 
                             niche_filling_layout = Some(Layout {
                                 variants: Variants::Multiple {
@@ -1273,7 +1264,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                     }
                 }
 
-                let tag_mask = !0u128 >> (128 - ity.size().bits());
+                let tag_mask = ity.size().unsigned_int_max();
                 let tag = Scalar {
                     value: Int(ity, signed),
                     valid_range: WrappingRange {
@@ -1283,7 +1274,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                 };
                 let mut abi = Abi::Aggregate { sized: true };
                 if tag.value.size(dl) == size {
-                    abi = Abi::Scalar(tag.clone());
+                    abi = Abi::Scalar(tag);
                 } else {
                     // Try to use a ScalarPair for all tagged enums.
                     let mut common_prim = None;
@@ -1303,7 +1294,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                             }
                         };
                         let prim = match field.abi {
-                            Abi::Scalar(ref scalar) => scalar.value,
+                            Abi::Scalar(scalar) => scalar.value,
                             _ => {
                                 common_prim = None;
                                 break;
@@ -1323,7 +1314,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         }
                     }
                     if let Some((prim, offset)) = common_prim {
-                        let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
+                        let pair = self.scalar_pair(tag, scalar_unit(prim));
                         let pair_offsets = match pair.fields {
                             FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                                 assert_eq!(memory_index, &[0, 1]);
@@ -1347,7 +1338,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                     abi = Abi::Uninhabited;
                 }
 
-                let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone());
+                let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
 
                 let tagged_layout = Layout {
                     variants: Variants::Multiple {
@@ -1372,8 +1363,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx Layout, LayoutError<'
                         // pick the layout with the larger niche; otherwise,
                         // pick tagged as it has simpler codegen.
                         cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| {
-                            let niche_size =
-                                layout.largest_niche.as_ref().map_or(0, |n| n.available(dl));
+                            let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl));
                             (layout.size, cmp::Reverse(niche_size))
                         })
                     }
@@ -1560,7 +1550,7 @@ fn generator_layout(
             value: Primitive::Int(discr_int, false),
             valid_range: WrappingRange { start: 0, end: max_discr },
         };
-        let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
+        let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag));
         let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
 
         let promoted_layouts = ineligible_locals
@@ -1832,7 +1822,7 @@ fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) {
                 }
             }
 
-            Variants::Multiple { ref tag, ref tag_encoding, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, .. } => {
                 debug!(
                     "print-type-size `{:#?}` adt general variants def {}",
                     layout.ty,
@@ -2023,6 +2013,12 @@ fn data_layout(&self) -> &TargetDataLayout {
     }
 }
 
+impl<'tcx> HasTargetSpec for TyCtxt<'tcx> {
+    fn target_spec(&self) -> &Target {
+        &self.sess.target
+    }
+}
+
 impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -2037,6 +2033,12 @@ fn data_layout(&self) -> &TargetDataLayout {
     }
 }
 
+impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+    fn target_spec(&self) -> &Target {
+        &self.sess.target
+    }
+}
+
 impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -2056,6 +2058,12 @@ fn data_layout(&self) -> &TargetDataLayout {
     }
 }
 
+impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> {
+    fn target_spec(&self) -> &Target {
+        self.tcx.target_spec()
+    }
+}
+
 impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx.tcx()
@@ -2138,10 +2146,10 @@ fn layout_of(&self, ty: Ty<'tcx>) -> Self::LayoutOfResult {
     #[inline]
     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() };
+        let tcx = self.tcx().at(span);
+
         MaybeResult::from(
-            self.tcx()
-                .at(span)
-                .layout_of(self.param_env().and(ty))
+            tcx.layout_of(self.param_env().and(ty))
                 .map_err(|err| self.handle_layout_err(err, span, ty)),
         )
     }
@@ -2240,7 +2248,7 @@ fn field_ty_or_layout(
             i: usize,
         ) -> TyMaybeWithLayout<'tcx> {
             let tcx = cx.tcx();
-            let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> {
+            let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
                 let layout = Layout::scalar(cx, tag.clone());
                 TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
             };
@@ -2329,7 +2337,7 @@ fn field_ty_or_layout(
                             .nth(i)
                             .unwrap(),
                     ),
-                    Variants::Multiple { ref tag, tag_field, .. } => {
+                    Variants::Multiple { tag, tag_field, .. } => {
                         if i == tag_field {
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
@@ -2347,7 +2355,7 @@ fn field_ty_or_layout(
                         }
 
                         // Discriminant field for enums (where applicable).
-                        Variants::Multiple { ref tag, .. } => {
+                        Variants::Multiple { tag, .. } => {
                             assert_eq!(i, 0);
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
@@ -2527,24 +2535,12 @@ fn ty_and_layout_pointee_info_at(
     }
 }
 
-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);
-
-        match *self {
-            Unknown(t) | SizeOverflow(t) => t.hash_stable(hcx, hasher),
-        }
-    }
-}
-
 impl<'tcx> ty::Instance<'tcx> {
     // NOTE(eddyb) this is private to avoid using it from outside of
-    // `FnAbi::of_instance` - any other uses are either too high-level
+    // `fn_abi_of_instance` - any other uses are either too high-level
     // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
     // or should go through `FnAbi` instead, to avoid losing any
-    // adjustments `FnAbi::of_instance` might be performing.
+    // adjustments `fn_abi_of_instance` might be performing.
     fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
         // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function.
         let ty = self.ty(tcx, ty::ParamEnv::reveal_all());
@@ -2641,34 +2637,6 @@ fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
     }
 }
 
-pub trait FnAbiExt<'tcx, C>
-where
-    C: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + HasTargetSpec,
-{
-    /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
-    ///
-    /// NB: this doesn't handle virtual calls - those should use `FnAbi::of_instance`
-    /// instead, where the instance is an `InstanceDef::Virtual`.
-    fn of_fn_ptr(cx: &C, sig: ty::PolyFnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
-
-    /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
-    /// direct calls to an `fn`.
-    ///
-    /// NB: that includes virtual calls, which are represented by "direct calls"
-    /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
-    fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self;
-
-    fn new_internal(
-        cx: &C,
-        sig: ty::PolyFnSig<'tcx>,
-        extra_args: &[Ty<'tcx>],
-        caller_location: Option<Ty<'tcx>>,
-        codegen_fn_attr_flags: CodegenFnAttrFlags,
-        make_self_ptr_thin: bool,
-    ) -> Self;
-    fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi);
-}
-
 /// Calculates whether a function's ABI can unwind or not.
 ///
 /// This takes two primary parameters:
@@ -2824,48 +2792,175 @@ 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<'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)
+/// Error produced by attempting to compute or adjust a `FnAbi`.
+#[derive(Clone, Debug, HashStable)]
+pub enum FnAbiError<'tcx> {
+    /// Error produced by a `layout_of` call, while computing `FnAbi` initially.
+    Layout(LayoutError<'tcx>),
+
+    /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
+    AdjustForForeignAbi(call::AdjustForForeignAbiError),
+}
+
+impl From<LayoutError<'tcx>> for FnAbiError<'tcx> {
+    fn from(err: LayoutError<'tcx>) -> Self {
+        Self::Layout(err)
     }
+}
 
-    fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self {
-        let sig = instance.fn_sig_for_fn_abi(cx.tcx());
+impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
+    fn from(err: call::AdjustForForeignAbiError) -> Self {
+        Self::AdjustForForeignAbi(err)
+    }
+}
 
-        let caller_location = if instance.def.requires_caller_location(cx.tcx()) {
-            Some(cx.tcx().caller_location_ty())
-        } else {
-            None
-        };
+impl<'tcx> fmt::Display for FnAbiError<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Layout(err) => err.fmt(f),
+            Self::AdjustForForeignAbi(err) => err.fmt(f),
+        }
+    }
+}
+
+// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
+// just for error handling.
+#[derive(Debug)]
+pub enum FnAbiRequest<'tcx> {
+    OfFnPtr { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
+    OfInstance { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>> },
+}
+
+/// Trait for contexts that want to be able to compute `FnAbi`s.
+/// This automatically gives access to `FnAbiOf`, through a blanket `impl`.
+pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
+    /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be
+    /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`).
+    type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>;
 
-        let attrs = cx.tcx().codegen_fn_attrs(instance.def_id()).flags;
+    /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a
+    /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
+    ///
+    /// Most `impl`s, which propagate `FnAbiError`s, should simply return `err`,
+    /// but this hook allows e.g. codegen to return only `&FnAbi` from its
+    /// `cx.fn_abi_of_*(...)`, without any `Result<...>` around it to deal with
+    /// (and any `FnAbiError`s are turned into fatal errors or ICEs).
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> <Self::FnAbiOfResult as MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>>::Error;
+}
+
+/// Blanket extension trait for contexts that can compute `FnAbi`s.
+pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
+    /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
+    ///
+    /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance`
+    /// instead, where the instance is an `InstanceDef::Virtual`.
+    #[inline]
+    fn fn_abi_of_fn_ptr(
+        &self,
+        sig: ty::PolyFnSig<'tcx>,
+        extra_args: &'tcx ty::List<Ty<'tcx>>,
+    ) -> Self::FnAbiOfResult {
+        // FIXME(eddyb) get a better `span` here.
+        let span = self.layout_tcx_at_span();
+        let tcx = self.tcx().at(span);
+
+        MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err(
+            |err| self.handle_fn_abi_err(err, span, FnAbiRequest::OfFnPtr { sig, extra_args }),
+        ))
+    }
 
-        call::FnAbi::new_internal(
-            cx,
-            sig,
-            extra_args,
-            caller_location,
-            attrs,
-            matches!(instance.def, ty::InstanceDef::Virtual(..)),
+    /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for
+    /// direct calls to an `fn`.
+    ///
+    /// NB: that includes virtual calls, which are represented by "direct calls"
+    /// to an `InstanceDef::Virtual` instance (of `<dyn Trait as Trait>::fn`).
+    #[inline]
+    fn fn_abi_of_instance(
+        &self,
+        instance: ty::Instance<'tcx>,
+        extra_args: &'tcx ty::List<Ty<'tcx>>,
+    ) -> Self::FnAbiOfResult {
+        // FIXME(eddyb) get a better `span` here.
+        let span = self.layout_tcx_at_span();
+        let tcx = self.tcx().at(span);
+
+        MaybeResult::from(
+            tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| {
+                // HACK(eddyb) at least for definitions of/calls to `Instance`s,
+                // we can get some kind of span even if one wasn't provided.
+                // However, we don't do this early in order to avoid calling
+                // `def_span` unconditionally (which may have a perf penalty).
+                let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) };
+                self.handle_fn_abi_err(err, span, FnAbiRequest::OfInstance { instance, extra_args })
+            }),
         )
     }
+}
 
-    fn new_internal(
-        cx: &C,
+impl<C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
+
+fn fn_abi_of_fn_ptr<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+    let (param_env, (sig, extra_args)) = query.into_parts();
+
+    LayoutCx { tcx, param_env }.fn_abi_new_uncached(
+        sig,
+        extra_args,
+        None,
+        CodegenFnAttrFlags::empty(),
+        false,
+    )
+}
+
+fn fn_abi_of_instance<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+    let (param_env, (instance, extra_args)) = query.into_parts();
+
+    let sig = instance.fn_sig_for_fn_abi(tcx);
+
+    let caller_location = if instance.def.requires_caller_location(tcx) {
+        Some(tcx.caller_location_ty())
+    } else {
+        None
+    };
+
+    let attrs = tcx.codegen_fn_attrs(instance.def_id()).flags;
+
+    LayoutCx { tcx, param_env }.fn_abi_new_uncached(
+        sig,
+        extra_args,
+        caller_location,
+        attrs,
+        matches!(instance.def, ty::InstanceDef::Virtual(..)),
+    )
+}
+
+impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
+    // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
+    // arguments of this method, into a separate `struct`.
+    fn fn_abi_new_uncached(
+        &self,
         sig: ty::PolyFnSig<'tcx>,
         extra_args: &[Ty<'tcx>],
         caller_location: Option<Ty<'tcx>>,
         codegen_fn_attr_flags: CodegenFnAttrFlags,
+        // FIXME(eddyb) replace this with something typed, like an `enum`.
         force_thin_self_ptr: bool,
-    ) -> Self {
-        debug!("FnAbi::new_internal({:?}, {:?})", sig, extra_args);
+    ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+        debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args);
 
-        let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
+        let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
 
-        let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
+        let conv = conv_from_spec_abi(self.tcx(), sig.abi);
 
         let mut inputs = sig.inputs();
         let extra_args = if sig.abi == RustCall {
@@ -2892,7 +2987,7 @@ fn new_internal(
             extra_args.to_vec()
         };
 
-        let target = &cx.tcx().sess.target;
+        let target = &self.tcx.sess.target;
         let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl");
         let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
         let linux_s390x_gnu_like =
@@ -2906,7 +3001,7 @@ fn new_internal(
 
         // Handle safe Rust thin and fat pointers.
         let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
-                                      scalar: &Scalar,
+                                      scalar: Scalar,
                                       layout: TyAndLayout<'tcx>,
                                       offset: Size,
                                       is_return: bool| {
@@ -2921,11 +3016,11 @@ fn new_internal(
                 return;
             }
 
-            if !scalar.valid_range.contains_zero() {
+            if !scalar.valid_range.contains(0) {
                 attrs.set(ArgAttribute::NonNull);
             }
 
-            if let Some(pointee) = layout.pointee_info_at(cx, offset) {
+            if let Some(pointee) = layout.pointee_info_at(self, offset) {
                 if let Some(kind) = pointee.safe {
                     attrs.pointee_align = Some(pointee.align);
 
@@ -2969,20 +3064,20 @@ fn new_internal(
             }
         };
 
-        let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| {
+        let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
             let is_return = arg_idx.is_none();
 
-            let layout = cx.layout_of(ty);
+            let layout = self.layout_of(ty)?;
             let layout = if force_thin_self_ptr && arg_idx == Some(0) {
                 // Don't pass the vtable, it's not an argument of the virtual fn.
                 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
                 // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
-                make_thin_self_ptr(cx, layout)
+                make_thin_self_ptr(self, layout)
             } else {
                 layout
             };
 
-            let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
+            let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
                 let mut attrs = ArgAttributes::new();
                 adjust_for_rust_scalar(&mut attrs, scalar, *layout, offset, is_return);
                 attrs
@@ -3003,11 +3098,11 @@ fn new_internal(
                 }
             }
 
-            arg
+            Ok(arg)
         };
 
         let mut fn_abi = FnAbi {
-            ret: arg_of(sig.output(), None),
+            ret: arg_of(sig.output(), None)?,
             args: inputs
                 .iter()
                 .cloned()
@@ -3015,20 +3110,24 @@ fn new_internal(
                 .chain(caller_location)
                 .enumerate()
                 .map(|(i, ty)| arg_of(ty, Some(i)))
-                .collect(),
+                .collect::<Result<_, _>>()?,
             c_variadic: sig.c_variadic,
             fixed_count: inputs.len(),
             conv,
-            can_unwind: fn_can_unwind(cx.tcx(), codegen_fn_attr_flags, sig.abi),
+            can_unwind: fn_can_unwind(self.tcx(), codegen_fn_attr_flags, sig.abi),
         };
-        fn_abi.adjust_for_abi(cx, sig.abi);
-        debug!("FnAbi::new_internal = {:?}", fn_abi);
-        fn_abi
+        self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
+        debug!("fn_abi_new_uncached = {:?}", fn_abi);
+        Ok(self.tcx.arena.alloc(fn_abi))
     }
 
-    fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
+    fn fn_abi_adjust_for_abi(
+        &self,
+        fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
+        abi: SpecAbi,
+    ) -> Result<(), FnAbiError<'tcx>> {
         if abi == SpecAbi::Unadjusted {
-            return;
+            return Ok(());
         }
 
         if abi == SpecAbi::Rust
@@ -3065,7 +3164,7 @@ fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
                     // anyway, we control all calls to it in libstd.
                     Abi::Vector { .. }
                         if abi != SpecAbi::PlatformIntrinsic
-                            && cx.tcx().sess.target.simd_types_indirect =>
+                            && self.tcx.sess.target.simd_types_indirect =>
                     {
                         arg.make_indirect();
                         return;
@@ -3076,7 +3175,7 @@ fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
 
                 // Pass and return structures up to 2 pointers in size by value, matching `ScalarPair`.
                 // LLVM will usually pass these in 2 registers, which is more efficient than by-ref.
-                let max_by_val_size = Pointer.size(cx) * 2;
+                let max_by_val_size = Pointer.size(self) * 2;
                 let size = arg.layout.size;
 
                 if arg.layout.is_unsized() || size > max_by_val_size {
@@ -3088,16 +3187,15 @@ fn adjust_for_abi(&mut self, cx: &C, abi: SpecAbi) {
                     arg.cast_to(Reg { kind: RegKind::Integer, size });
                 }
             };
-            fixup(&mut self.ret);
-            for arg in &mut self.args {
+            fixup(&mut fn_abi.ret);
+            for arg in &mut fn_abi.args {
                 fixup(arg);
             }
-            return;
+        } else {
+            fn_abi.adjust_for_foreign_abi(self, abi)?;
         }
 
-        if let Err(msg) = self.adjust_for_cabi(cx, abi) {
-            cx.tcx().sess.fatal(&msg);
-        }
+        Ok(())
     }
 }
 
index fddfd6e435c0550e586f0ffa732a35784ab33f99..777c6035be831c503043aacd9e89ca503952979c 100644 (file)
@@ -127,7 +127,7 @@ pub struct ResolverOutputs {
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
     pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
-    pub export_map: ExportMap<LocalDefId>,
+    pub export_map: ExportMap,
     pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
@@ -1377,6 +1377,8 @@ fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHas
 pub struct Destructor {
     /// The `DefId` of the destructor method
     pub did: DefId,
+    /// The constness of the destructor method
+    pub constness: hir::Constness,
 }
 
 bitflags! {
index 15a8888ee65eda376002df70eb59b33098f97e69..154b26464a804af2fc4f3963f9d26b826eeb4c92 100644 (file)
@@ -48,6 +48,7 @@
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
 use rustc_session::Limits;
+use rustc_target::abi;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast as ast;
index 9d1be212f5b8c49771a62de47cc48263bc8032f7..2c786538014ff20421324e5927de8a613caaf4e0 100644 (file)
@@ -639,6 +639,15 @@ fn check_const_value_eq<R: TypeRelation<'tcx>>(
             get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
         }
 
+        (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
+            if a.ty.is_ref() || b.ty.is_ref() =>
+        {
+            if a.ty.is_ref() && b.ty.is_ref() {
+                alloc_a == alloc_b
+            } else {
+                false
+            }
+        }
         (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
             let a_destructured = tcx.destructure_const(relation.param_env().and(a));
             let b_destructured = tcx.destructure_const(relation.param_env().and(b));
index 1b8e94260b9b5d73f0228dc5cf7b1aaffd5d262d..2ec06d472fee0b9889f33ff146c267d2ee707f82 100644 (file)
@@ -45,18 +45,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-fn signed_min(size: Size) -> i128 {
-    size.sign_extend(1_u128 << (size.bits() - 1)) as i128
-}
-
-fn signed_max(size: Size) -> i128 {
-    i128::MAX >> (128 - size.bits())
-}
-
-fn unsigned_max(size: Size) -> u128 {
-    u128::MAX >> (128 - size.bits())
-}
-
 fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
     let (int, signed) = match *ty.kind() {
         Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
@@ -74,8 +62,8 @@ pub fn wrap_incr(self, tcx: TyCtxt<'tcx>) -> Self {
     pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
         let (size, signed) = int_size_and_signed(tcx, self.ty);
         let (val, oflo) = if signed {
-            let min = signed_min(size);
-            let max = signed_max(size);
+            let min = size.signed_int_min();
+            let max = size.signed_int_max();
             let val = size.sign_extend(self.val) as i128;
             assert!(n < (i128::MAX as u128));
             let n = n as i128;
@@ -86,7 +74,7 @@ pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
             let val = size.truncate(val);
             (val, oflo)
         } else {
-            let max = unsigned_max(size);
+            let max = size.unsigned_int_max();
             let val = self.val;
             let oflo = val > max - n;
             let val = if oflo { n - (max - val) - 1 } else { val + n };
@@ -336,16 +324,16 @@ pub fn calculate_dtor(
         self.ensure().coherent_trait(drop_trait);
 
         let ty = self.type_of(adt_did);
-        let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
+        let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
                 if validate(self, impl_did).is_ok() {
-                    return Some(item.def_id);
+                    return Some((item.def_id, self.impl_constness(impl_did)));
                 }
             }
             None
-        });
+        })?;
 
-        Some(ty::Destructor { did: dtor_did? })
+        Some(ty::Destructor { did, constness })
     }
 
     /// Returns the set of types that are required to be alive in
@@ -621,7 +609,8 @@ pub fn numeric_max_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<
         let val = match self.kind() {
             ty::Int(_) | ty::Uint(_) => {
                 let (size, signed) = int_size_and_signed(tcx, self);
-                let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+                let val =
+                    if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() };
                 Some(val)
             }
             ty::Char => Some(std::char::MAX as u128),
@@ -640,7 +629,7 @@ pub fn numeric_min_val(&'tcx self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ty::Const<
         let val = match self.kind() {
             ty::Int(_) | ty::Uint(_) => {
                 let (size, signed) = int_size_and_signed(tcx, self);
-                let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
+                let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 };
                 Some(val)
             }
             ty::Char => Some(0),
index e9fbc1b186d19fb361a4f5789c8ce2edcb2c9f9c..998b80a36c2f7eb73ecb7e920eeb6969cfa89450 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_mir_build"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index bbb2f89fda9399fd3cf3c7436b46160ec249a0be..b627b0763a286c2822d250178d73b05e12bb733c 100644 (file)
@@ -20,7 +20,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         expr: &Expr<'tcx>,
     ) -> BlockAnd<Operand<'tcx>> {
         let local_scope = self.local_scope();
-        self.as_operand(block, Some(local_scope), expr)
+        self.as_operand(block, Some(local_scope), expr, None)
     }
 
     /// Returns an operand suitable for use until the end of the current scope expression and
@@ -85,6 +85,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// temporary `tmp = x`, so that we capture the value of `x` at
     /// this time.
     ///
+    /// If we end up needing to create a temporary, then we will use
+    /// `local_info` as its `LocalInfo`, unless `as_temporary`
+    /// has already assigned it a non-`None` `LocalInfo`.
+    /// Normally, you should use `None` for `local_info`
+    ///
     /// The operand is known to be live until the end of `scope`.
     ///
     /// Like `as_local_call_operand`, except that the argument will
@@ -94,15 +99,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         mut block: BasicBlock,
         scope: Option<region::Scope>,
         expr: &Expr<'tcx>,
+        local_info: Option<Box<LocalInfo<'tcx>>>,
     ) -> BlockAnd<Operand<'tcx>> {
-        debug!("as_operand(block={:?}, expr={:?})", block, expr);
+        debug!("as_operand(block={:?}, expr={:?} local_info={:?})", block, expr, local_info);
         let this = self;
 
         if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
             let source_info = this.source_info(expr.span);
             let region_scope = (region_scope, source_info);
             return this.in_scope(region_scope, lint_level, |this| {
-                this.as_operand(block, scope, &this.thir[value])
+                this.as_operand(block, scope, &this.thir[value], local_info)
             });
         }
 
@@ -115,6 +121,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             Category::Place | Category::Rvalue(..) => {
                 let operand = unpack!(block = this.as_temp(block, scope, expr, Mutability::Mut));
+                if this.local_decls[operand].local_info.is_none() {
+                    this.local_decls[operand].local_info = local_info;
+                }
                 block.and(Operand::Move(Place::from(operand)))
             }
         }
@@ -167,6 +176,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        this.as_operand(block, scope, expr)
+        this.as_operand(block, scope, expr, None)
     }
 }
index 68de1af613d9f20d7b2e1f18a5082ed8486f2a51..4b40faaf1956db04f344bf947ddcca0add3563e4 100644 (file)
@@ -52,16 +52,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
             ExprKind::Repeat { value, count } => {
                 let value_operand =
-                    unpack!(block = this.as_operand(block, scope, &this.thir[value]));
+                    unpack!(block = this.as_operand(block, scope, &this.thir[value], None));
                 block.and(Rvalue::Repeat(value_operand, count))
             }
             ExprKind::Binary { op, lhs, rhs } => {
-                let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs]));
-                let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs]));
+                let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs], None));
+                let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs], None));
                 this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
             }
             ExprKind::Unary { op, arg } => {
-                let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg]));
+                let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg], None));
                 // Check for -MIN on signed integers
                 if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
                     let bool_ty = this.tcx.types.bool;
@@ -116,11 +116,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 block.and(Rvalue::Use(Operand::Move(Place::from(result))))
             }
             ExprKind::Cast { source } => {
-                let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
+                let source =
+                    unpack!(block = this.as_operand(block, scope, &this.thir[source], None));
                 block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
             }
             ExprKind::Pointer { cast, source } => {
-                let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
+                let source =
+                    unpack!(block = this.as_operand(block, scope, &this.thir[source], None));
                 block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
             }
             ExprKind::Array { ref fields } => {
@@ -155,7 +157,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fields: Vec<_> = fields
                     .into_iter()
                     .copied()
-                    .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
+                    .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None)))
                     .collect();
 
                 block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(el_ty)), fields))
@@ -166,7 +168,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fields: Vec<_> = fields
                     .into_iter()
                     .copied()
-                    .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
+                    .map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f], None)))
                     .collect();
 
                 block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields))
@@ -242,7 +244,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                             &this.thir[arg],
                                         )
                                     ),
-                                    _ => unpack!(block = this.as_operand(block, scope, upvar)),
+                                    _ => {
+                                        unpack!(block = this.as_operand(block, scope, upvar, None))
+                                    }
                                 }
                             }
                         }
@@ -304,7 +308,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     Category::of(&expr.kind),
                     Some(Category::Rvalue(RvalueFunc::AsRvalue))
                 ));
-                let operand = unpack!(block = this.as_operand(block, scope, expr));
+                let operand = unpack!(block = this.as_operand(block, scope, expr, None));
                 block.and(Rvalue::Use(operand))
             }
         }
@@ -494,9 +498,8 @@ fn limit_capture_mutability(
     // Helper to get a `-1` value of the appropriate type
     fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let param_ty = ty::ParamEnv::empty().and(ty);
-        let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
-        let n = (!0u128) >> (128 - bits);
-        let literal = ty::Const::from_bits(self.tcx, n, param_ty);
+        let size = self.tcx.layout_of(param_ty).unwrap().size;
+        let literal = ty::Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
 
         self.literal_operand(span, literal)
     }
index e30e758e63779db24c094a481e44e7672586c761..1803a18441ce20cffc8fba87ca09fae02193d7b8 100644 (file)
@@ -326,10 +326,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let fields_map: FxHashMap<_, _> = fields
                     .into_iter()
                     .map(|f| {
+                        let local_info = Box::new(LocalInfo::AggregateTemp);
                         (
                             f.name,
                             unpack!(
-                                block = this.as_operand(block, Some(scope), &this.thir[f.expr])
+                                block = this.as_operand(
+                                    block,
+                                    Some(scope),
+                                    &this.thir[f.expr],
+                                    Some(local_info)
+                                )
                             ),
                         )
                     })
@@ -508,7 +514,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
             ExprKind::Yield { value } => {
                 let scope = this.local_scope();
-                let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value]));
+                let value =
+                    unpack!(block = this.as_operand(block, Some(scope), &this.thir[value], None));
                 let resume = this.cfg.start_new_block();
                 this.cfg.terminate(
                     block,
index ba94e15444a1905f5c7efcd3da76cca26eab0edd..4df073c40e22c318eb620685d295283cf0ba4a15 100644 (file)
@@ -900,10 +900,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
 struct Binding<'tcx> {
     span: Span,
     source: Place<'tcx>,
-    name: Symbol,
     var_id: HirId,
-    var_ty: Ty<'tcx>,
-    mutability: Mutability,
     binding_mode: BindingMode,
 }
 
@@ -2063,7 +2060,7 @@ fn ascribe_types<'b>(
                 source_info.span, ascription.source, ascription.user_ty,
             );
 
-            let user_ty = ascription.user_ty.clone().user_ty(
+            let user_ty = ascription.user_ty.user_ty(
                 &mut self.canonical_user_type_annotations,
                 ascription.source.ty(&self.local_decls, self.tcx).ty,
                 source_info.span,
index 1feb8b0d7a06d4d670606ad508537afe718fa858..4ce26cc8dff46a10f4ecde92cba0feb3833425ac 100644 (file)
@@ -176,17 +176,22 @@ fn simplify_match_pair<'pat>(
                 Ok(())
             }
 
-            PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
+            PatKind::Binding {
+                name: _,
+                mutability: _,
+                mode,
+                var,
+                ty: _,
+                ref subpattern,
+                is_primary: _,
+            } => {
                 if let Ok(place_resolved) =
                     match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
                 {
                     candidate.bindings.push(Binding {
-                        name,
-                        mutability,
                         span: match_pair.pattern.span,
                         source: place_resolved.into_place(self.tcx, self.typeck_results),
                         var_id: var,
-                        var_ty: ty,
                         binding_mode: mode,
                     });
                 }
index 0a760a740dcaea5801a8b4bcb854d19ba6758d50..4108ad50470b711f217ecdcfe9d07b24672e10cc 100644 (file)
@@ -44,13 +44,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     let body_owner_kind = tcx.hir().body_owner_kind(id);
     let typeck_results = tcx.typeck_opt_const_arg(def);
 
-    // Ensure unsafeck is ran before we steal the THIR.
+    // Ensure unsafeck and abstract const building is ran before we steal the THIR.
+    // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
+    // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
+    // THIR has been stolen if we haven't computed this query yet.
     match def {
         ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
-            tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did))
+            tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
+            drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did)));
         }
         ty::WithOptConstParam { did, const_param_did: None } => {
-            tcx.ensure().thir_check_unsafety(did)
+            tcx.ensure().thir_check_unsafety(did);
+            drop(tcx.thir_abstract_const(did));
         }
     }
 
index bd8d14fcd012c2ec5965940a517e50b568c234ef..b74208edafea6172643d9c02f41a5a8cfb7679d2 100644 (file)
@@ -118,9 +118,6 @@ struct Scope {
     /// the region span of this scope within source code.
     region_scope: region::Scope,
 
-    /// the span of that region_scope
-    region_scope_span: Span,
-
     /// set of places to drop when exiting this scope. This starts
     /// out empty but grows as variables are declared during the
     /// building process. This is a stack, so we always drop from the
@@ -420,7 +417,6 @@ fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo), vis_scope: S
         self.scopes.push(Scope {
             source_scope: vis_scope,
             region_scope: region_scope.0,
-            region_scope_span: region_scope.1.span,
             drops: vec![],
             moved_locals: vec![],
             cached_unwind_block: None,
index 05a5fcef16ae53adb459e44413e0669f459ccfb5..0e82b187201422d4983f105718266d74e946fb1d 100644 (file)
@@ -1,5 +1,5 @@
 use crate::build::ExprCategory;
-use crate::thir::visit::{self, Visitor};
+use rustc_middle::thir::visit::{self, Visitor};
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
index e5123d8ef0c997e972d34768e5be1689b8546157..ddbe1b0b69c1eb9dba9686063215b7c4086f9618 100644 (file)
@@ -11,4 +11,3 @@
 crate mod pattern;
 
 mod util;
-pub mod visit;
index b34c1e07be71c61ff6d2673d67e1ea2bfe1509e6..4c51b9207bb750b03536b53de29c4183ec1aa2f7 100644 (file)
@@ -14,8 +14,9 @@
 use rustc_hir::{HirId, Pat};
 use rustc_middle::thir::PatKind;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
-use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
+use rustc_session::lint::builtin::{
+    BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
+};
 use rustc_session::Session;
 use rustc_span::{DesugaringKind, ExpnKind, Span};
 use std::slice;
@@ -559,7 +560,7 @@ fn non_exhaustive_match<'p, 'tcx>(
     err.emit();
 }
 
-fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
+crate fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
     const LIMIT: usize = 3;
     match witnesses {
         [] => bug!(),
@@ -576,7 +577,7 @@ fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
     }
 }
 
-fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
+crate fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
     format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns)
 }
 
index bbb5de34d1860a84011421cfebb78e1130a76488..847b89f0464f6fa474ea962ed70448b24711a903 100644 (file)
@@ -322,16 +322,18 @@ fn recur(
                     && !self.saw_const_match_lint.get()
                 {
                     self.saw_const_match_lint.set(true);
-                    let msg = format!(
-                        "to use a constant of type `{}` in a pattern, \
-                        `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                        cv.ty, cv.ty,
-                    );
                     tcx.struct_span_lint_hir(
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         id,
                         span,
-                        |lint| lint.build(&msg).emit(),
+                        |lint| {
+                            let msg = format!(
+                                "to use a constant of type `{}` in a pattern, \
+                                 `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                                cv.ty, cv.ty,
+                            );
+                            lint.build(&msg).emit()
+                        },
                     );
                 }
                 // Since we are behind a reference, we can just bubble the error up so we get a
index ace13ea44624d627b8959b0328e7e8310d15ba68..cee2a4db0a8b3b6649bf487801d361f8ff97ca6f 100644 (file)
@@ -606,8 +606,9 @@ pub(super) enum Constructor<'tcx> {
     /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
     NonExhaustive,
     /// Stands for constructors that are not seen in the matrix, as explained in the documentation
-    /// for [`SplitWildcard`].
-    Missing,
+    /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns`
+    /// lint.
+    Missing { nonexhaustive_enum_missing_real_variants: bool },
     /// Wildcard pattern.
     Wildcard,
 }
@@ -617,6 +618,10 @@ pub(super) fn is_wildcard(&self) -> bool {
         matches!(self, Wildcard)
     }
 
+    pub(super) fn is_non_exhaustive(&self) -> bool {
+        matches!(self, NonExhaustive)
+    }
+
     fn as_int_range(&self) -> Option<&IntRange> {
         match self {
             IntRange(range) => Some(range),
@@ -756,7 +761,7 @@ pub(super) fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self)
             // Wildcards cover anything
             (_, Wildcard) => true,
             // The missing ctors are not covered by anything in the matrix except wildcards.
-            (Missing | Wildcard, _) => false,
+            (Missing { .. } | Wildcard, _) => false,
 
             (Single, Single) => true,
             (Variant(self_id), Variant(other_id)) => self_id == other_id,
@@ -829,7 +834,7 @@ fn is_covered_by_any<'p>(
                 .any(|other| slice.is_covered_by(other)),
             // This constructor is never covered by anything else
             NonExhaustive => false,
-            Str(..) | FloatRange(..) | Opaque | Missing | Wildcard => {
+            Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard => {
                 span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self)
             }
         }
@@ -919,8 +924,14 @@ pub(super) fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
                     && !cx.tcx.features().exhaustive_patterns
                     && !pcx.is_top_level;
 
-                if is_secretly_empty || is_declared_nonexhaustive {
+                if is_secretly_empty {
                     smallvec![NonExhaustive]
+                } else if is_declared_nonexhaustive {
+                    def.variants
+                        .indices()
+                        .map(|idx| Variant(idx))
+                        .chain(Some(NonExhaustive))
+                        .collect()
                 } else if cx.tcx.features().exhaustive_patterns {
                     // If `exhaustive_patterns` is enabled, we exclude variants known to be
                     // uninhabited.
@@ -975,6 +986,7 @@ pub(super) fn new<'p>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Self {
             // This type is one for which we cannot list constructors, like `str` or `f64`.
             _ => smallvec![NonExhaustive],
         };
+
         SplitWildcard { matrix_ctors: Vec::new(), all_ctors }
     }
 
@@ -1039,7 +1051,17 @@ pub(super) fn iter_missing<'a, 'p>(
             // sometimes prefer reporting the list of constructors instead of just `_`.
             let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
             let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing {
-                Missing
+                if pcx.is_non_exhaustive {
+                    Missing {
+                        nonexhaustive_enum_missing_real_variants: self
+                            .iter_missing(pcx)
+                            .filter(|c| !c.is_non_exhaustive())
+                            .next()
+                            .is_some(),
+                    }
+                } else {
+                    Missing { nonexhaustive_enum_missing_real_variants: false }
+                }
             } else {
                 Wildcard
             };
@@ -1176,7 +1198,12 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
                 }
                 _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
             },
-            Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Missing
+            Str(..)
+            | FloatRange(..)
+            | IntRange(..)
+            | NonExhaustive
+            | Opaque
+            | Missing { .. }
             | Wildcard => Fields::Slice(&[]),
         };
         debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
@@ -1189,15 +1216,18 @@ pub(super) fn wildcards(pcx: PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'t
     /// This is roughly the inverse of `specialize_constructor`.
     ///
     /// Examples:
-    /// `ctor`: `Constructor::Single`
-    /// `ty`: `Foo(u32, u32, u32)`
-    /// `self`: `[10, 20, _]`
+    ///
+    /// ```text
+    /// ctor: `Constructor::Single`
+    /// ty: `Foo(u32, u32, u32)`
+    /// self: `[10, 20, _]`
     /// returns `Foo(10, 20, _)`
     ///
-    /// `ctor`: `Constructor::Variant(Option::Some)`
-    /// `ty`: `Option<bool>`
-    /// `self`: `[false]`
+    /// ctor: `Constructor::Variant(Option::Some)`
+    /// ty: `Option<bool>`
+    /// self: `[false]`
     /// returns `Some(false)`
+    /// ```
     pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Pat<'tcx> {
         let subpatterns_and_indices = self.patterns_and_indices();
         let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p).cloned();
@@ -1265,7 +1295,7 @@ pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>)
             NonExhaustive => PatKind::Wild,
             Wildcard => return Pat::wildcard_from_ty(pcx.ty),
             Opaque => bug!("we should not try to apply an opaque constructor"),
-            Missing => bug!(
+            Missing { .. } => bug!(
                 "trying to apply the `Missing` constructor; this should have been done in `apply_constructors`"
             ),
         };
index 344006e9fb4c902af74703640f3b0036b968db12..f4255713e2a378bebca4e2c010c5c7b9447565c6 100644 (file)
 //! The details are not necessary to understand this file, so we explain them in
 //! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function.
 
+use self::ArmType::*;
 use self::Usefulness::*;
-use self::WitnessPreference::*;
 
+use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
 use super::deconstruct_pat::{Constructor, Fields, SplitWildcard};
 use super::{PatternFoldable, PatternFolder};
 
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 
+use hir::def_id::DefId;
+use hir::HirId;
 use rustc_arena::TypedArena;
-use rustc_hir::def_id::DefId;
-use rustc_hir::HirId;
+use rustc_hir as hir;
 use rustc_middle::thir::{Pat, PatKind};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
@@ -343,6 +346,8 @@ pub(super) struct PatCtxt<'a, 'p, 'tcx> {
     /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
     /// subpattern.
     pub(super) is_top_level: bool,
+    /// Wether the current pattern is from a `non_exhaustive` enum.
+    pub(super) is_non_exhaustive: bool,
 }
 
 impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
@@ -862,7 +867,7 @@ fn unsplit_or_pat(mut self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>)
 /// of potential unreachable sub-patterns (in the presence of or-patterns). When checking
 /// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of
 /// witnesses of non-exhaustiveness when there are any.
-/// Which variant to use is dictated by `WitnessPreference`.
+/// Which variant to use is dictated by `ArmType`.
 #[derive(Clone, Debug)]
 enum Usefulness<'p, 'tcx> {
     /// Carries a set of subpatterns that have been found to be reachable. If empty, this indicates
@@ -877,16 +882,24 @@ enum Usefulness<'p, 'tcx> {
 }
 
 impl<'p, 'tcx> Usefulness<'p, 'tcx> {
-    fn new_useful(preference: WitnessPreference) -> Self {
+    fn new_useful(preference: ArmType) -> Self {
         match preference {
-            ConstructWitness => WithWitnesses(vec![Witness(vec![])]),
-            LeaveOutWitness => NoWitnesses(SubPatSet::full()),
+            FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]),
+            RealArm => NoWitnesses(SubPatSet::full()),
         }
     }
-    fn new_not_useful(preference: WitnessPreference) -> Self {
+
+    fn new_not_useful(preference: ArmType) -> Self {
         match preference {
-            ConstructWitness => WithWitnesses(vec![]),
-            LeaveOutWitness => NoWitnesses(SubPatSet::empty()),
+            FakeExtraWildcard => WithWitnesses(vec![]),
+            RealArm => NoWitnesses(SubPatSet::empty()),
+        }
+    }
+
+    fn is_useful(&self) -> bool {
+        match self {
+            Usefulness::NoWitnesses(set) => !set.is_empty(),
+            Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(),
         }
     }
 
@@ -903,7 +916,7 @@ fn extend(&mut self, other: Self) {
 
     /// When trying several branches and each returns a `Usefulness`, we need to combine the
     /// results together.
-    fn merge(pref: WitnessPreference, usefulnesses: impl Iterator<Item = Self>) -> Self {
+    fn merge(pref: ArmType, usefulnesses: impl Iterator<Item = Self>) -> Self {
         let mut ret = Self::new_not_useful(pref);
         for u in usefulnesses {
             ret.extend(u);
@@ -926,7 +939,7 @@ fn unsplit_or_pat(self, alt_id: usize, alt_count: usize, pat: &'p Pat<'tcx>) ->
         }
     }
 
-    /// After calculating usefulness after a specialization, call this to recontruct a usefulness
+    /// After calculating usefulness after a specialization, call this to reconstruct a usefulness
     /// that makes sense for the matrix pre-specialization. This new usefulness can then be merged
     /// with the results of specializing with the other constructors.
     fn apply_constructor(
@@ -939,19 +952,31 @@ fn apply_constructor(
         match self {
             WithWitnesses(witnesses) if witnesses.is_empty() => WithWitnesses(witnesses),
             WithWitnesses(witnesses) => {
-                let new_witnesses = if matches!(ctor, Constructor::Missing) {
-                    let mut split_wildcard = SplitWildcard::new(pcx);
-                    split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
-                    // Construct for each missing constructor a "wild" version of this
-                    // constructor, that matches everything that can be built with
-                    // it. For example, if `ctor` is a `Constructor::Variant` for
-                    // `Option::Some`, we get the pattern `Some(_)`.
-                    let new_patterns: Vec<_> = split_wildcard
-                        .iter_missing(pcx)
-                        .map(|missing_ctor| {
-                            Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
-                        })
-                        .collect();
+                let new_witnesses = if let Constructor::Missing { .. } = ctor {
+                    // We got the special `Missing` constructor, so each of the missing constructors
+                    // gives a new pattern that is not caught by the match. We list those patterns.
+                    let new_patterns = if pcx.is_non_exhaustive {
+                        // Here we don't want the user to try to list all variants, we want them to add
+                        // a wildcard, so we only suggest that.
+                        vec![
+                            Fields::wildcards(pcx, &Constructor::NonExhaustive)
+                                .apply(pcx, &Constructor::NonExhaustive),
+                        ]
+                    } else {
+                        let mut split_wildcard = SplitWildcard::new(pcx);
+                        split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+                        // Construct for each missing constructor a "wild" version of this
+                        // constructor, that matches everything that can be built with
+                        // it. For example, if `ctor` is a `Constructor::Variant` for
+                        // `Option::Some`, we get the pattern `Some(_)`.
+                        split_wildcard
+                            .iter_missing(pcx)
+                            .map(|missing_ctor| {
+                                Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+                            })
+                            .collect()
+                    };
+
                     witnesses
                         .into_iter()
                         .flat_map(|witness| {
@@ -976,9 +1001,9 @@ fn apply_constructor(
 }
 
 #[derive(Copy, Clone, Debug)]
-enum WitnessPreference {
-    ConstructWitness,
-    LeaveOutWitness,
+enum ArmType {
+    FakeExtraWildcard,
+    RealArm,
 }
 
 /// A witness of non-exhaustiveness for error reporting, represented
@@ -1056,6 +1081,32 @@ fn apply_constructor<'p>(
     }
 }
 
+/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+/// is not exhaustive enough.
+///
+/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
+fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
+    cx: &MatchCheckCtxt<'p, 'tcx>,
+    scrut_ty: Ty<'tcx>,
+    sp: Span,
+    hir_id: HirId,
+    witnesses: Vec<Pat<'tcx>>,
+) {
+    let joined_patterns = joined_uncovered_patterns(&witnesses);
+    cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| {
+        let mut lint = build.build("some variants are not matched explicitly");
+        lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+        lint.help(
+            "ensure that all variants are matched explicitly by adding the suggested match arms",
+        );
+        lint.note(&format!(
+            "the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+            scrut_ty,
+        ));
+        lint.emit();
+    });
+}
+
 /// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
 /// The algorithm from the paper has been modified to correctly handle empty
 /// types. The changes are:
@@ -1086,7 +1137,7 @@ fn is_useful<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
-    witness_preference: WitnessPreference,
+    witness_preference: ArmType,
     hir_id: HirId,
     is_under_guard: bool,
     is_top_level: bool,
@@ -1113,7 +1164,8 @@ fn is_useful<'p, 'tcx>(
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
     let ty = matrix.heads().next().map_or(v.head().ty, |r| r.ty);
-    let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
+    let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
+    let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level, is_non_exhaustive };
 
     // If the first pattern is an or-pattern, expand it.
     let ret = if is_or_pat(v.head()) {
@@ -1148,6 +1200,7 @@ fn is_useful<'p, 'tcx>(
         }
         // We split the head constructor of `v`.
         let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx));
+        let is_non_exhaustive_and_wild = is_non_exhaustive && v_ctor.is_wildcard();
         // For each constructor, we compute whether there's a value that starts with it that would
         // witness the usefulness of `v`.
         let start_matrix = &matrix;
@@ -1160,10 +1213,46 @@ fn is_useful<'p, 'tcx>(
             let v = v.pop_head_constructor(&ctor_wild_subpatterns);
             let usefulness =
                 is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
+
+            // When all the conditions are met we have a match with a `non_exhaustive` enum
+            // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
+            // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
+            if is_non_exhaustive_and_wild
+                // We check that the match has a wildcard pattern and that that wildcard is useful,
+                // meaning there are variants that are covered by the wildcard. Without the check
+                // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
+                && usefulness.is_useful() && matches!(witness_preference, RealArm)
+                && matches!(
+                    &ctor,
+                    Constructor::Missing { nonexhaustive_enum_missing_real_variants: true }
+                )
+            {
+                let patterns = {
+                    let mut split_wildcard = SplitWildcard::new(pcx);
+                    split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+                    // Construct for each missing constructor a "wild" version of this
+                    // constructor, that matches everything that can be built with
+                    // it. For example, if `ctor` is a `Constructor::Variant` for
+                    // `Option::Some`, we get the pattern `Some(_)`.
+                    split_wildcard
+                        .iter_missing(pcx)
+                        // Filter out the `Constructor::NonExhaustive` variant it's meaningless
+                        // to our lint
+                        .filter(|c| !c.is_non_exhaustive())
+                        .map(|missing_ctor| {
+                            Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+                        })
+                        .collect::<Vec<_>>()
+                };
+
+                lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns);
+            }
+
             usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
         });
         Usefulness::merge(witness_preference, usefulnesses)
     };
+
     debug!(?ret);
     ret
 }
@@ -1214,8 +1303,7 @@ fn is_useful<'p, 'tcx>(
         .copied()
         .map(|arm| {
             let v = PatStack::from_pattern(arm.pat);
-            let usefulness =
-                is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true);
+            let usefulness = is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true);
             if !arm.has_guard {
                 matrix.push(v);
             }
@@ -1232,7 +1320,7 @@ fn is_useful<'p, 'tcx>(
 
     let wild_pattern = cx.pattern_arena.alloc(Pat::wildcard_from_ty(scrut_ty));
     let v = PatStack::from_pattern(wild_pattern);
-    let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
+    let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true);
     let non_exhaustiveness_witnesses = match usefulness {
         WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
         NoWitnesses(_) => bug!(),
diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs
deleted file mode 100644 (file)
index 51c371b..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-use rustc_middle::thir::{self, *};
-use rustc_middle::ty::Const;
-
-pub trait Visitor<'a, 'tcx: 'a>: Sized {
-    fn thir(&self) -> &'a Thir<'tcx>;
-
-    fn visit_expr(&mut self, expr: &Expr<'tcx>) {
-        walk_expr(self, expr);
-    }
-
-    fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
-        walk_stmt(self, stmt);
-    }
-
-    fn visit_block(&mut self, block: &Block) {
-        walk_block(self, block);
-    }
-
-    fn visit_arm(&mut self, arm: &Arm<'tcx>) {
-        walk_arm(self, arm);
-    }
-
-    fn visit_pat(&mut self, pat: &Pat<'tcx>) {
-        walk_pat(self, pat);
-    }
-
-    fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
-}
-
-pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Expr<'tcx>) {
-    use ExprKind::*;
-    match expr.kind {
-        Scope { value, region_scope: _, lint_level: _ } => {
-            visitor.visit_expr(&visitor.thir()[value])
-        }
-        Box { value } => visitor.visit_expr(&visitor.thir()[value]),
-        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 {
-                visitor.visit_expr(&visitor.thir()[else_expr]);
-            }
-        }
-        Call { fun, ref args, ty: _, from_hir_call: _, fn_span: _ } => {
-            visitor.visit_expr(&visitor.thir()[fun]);
-            for &arg in &**args {
-                visitor.visit_expr(&visitor.thir()[arg]);
-            }
-        }
-        Deref { arg } => visitor.visit_expr(&visitor.thir()[arg]),
-        Binary { lhs, rhs, op: _ } | LogicalOp { lhs, rhs, op: _ } => {
-            visitor.visit_expr(&visitor.thir()[lhs]);
-            visitor.visit_expr(&visitor.thir()[rhs]);
-        }
-        Unary { arg, op: _ } => visitor.visit_expr(&visitor.thir()[arg]),
-        Cast { source } => visitor.visit_expr(&visitor.thir()[source]),
-        Use { source } => visitor.visit_expr(&visitor.thir()[source]),
-        NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
-        Pointer { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
-        Let { expr, .. } => {
-            visitor.visit_expr(&visitor.thir()[expr]);
-        }
-        Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
-        Match { scrutinee, ref arms } => {
-            visitor.visit_expr(&visitor.thir()[scrutinee]);
-            for &arm in &**arms {
-                visitor.visit_arm(&visitor.thir()[arm]);
-            }
-        }
-        Block { ref body } => visitor.visit_block(body),
-        Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
-            visitor.visit_expr(&visitor.thir()[lhs]);
-            visitor.visit_expr(&visitor.thir()[rhs]);
-        }
-        Field { lhs, name: _ } => visitor.visit_expr(&visitor.thir()[lhs]),
-        Index { lhs, index } => {
-            visitor.visit_expr(&visitor.thir()[lhs]);
-            visitor.visit_expr(&visitor.thir()[index]);
-        }
-        VarRef { id: _ } | UpvarRef { closure_def_id: _, var_hir_id: _ } => {}
-        Borrow { arg, borrow_kind: _ } => visitor.visit_expr(&visitor.thir()[arg]),
-        AddressOf { arg, mutability: _ } => visitor.visit_expr(&visitor.thir()[arg]),
-        Break { value, label: _ } => {
-            if let Some(value) = value {
-                visitor.visit_expr(&visitor.thir()[value])
-            }
-        }
-        Continue { label: _ } => {}
-        Return { value } => {
-            if let Some(value) = value {
-                visitor.visit_expr(&visitor.thir()[value])
-            }
-        }
-        ConstBlock { value } => visitor.visit_const(value),
-        Repeat { value, count } => {
-            visitor.visit_expr(&visitor.thir()[value]);
-            visitor.visit_const(count);
-        }
-        Array { ref fields } | Tuple { ref fields } => {
-            for &field in &**fields {
-                visitor.visit_expr(&visitor.thir()[field]);
-            }
-        }
-        Adt(box thir::Adt {
-            ref fields,
-            ref base,
-            adt_def: _,
-            variant_index: _,
-            substs: _,
-            user_ty: _,
-        }) => {
-            for field in &**fields {
-                visitor.visit_expr(&visitor.thir()[field.expr]);
-            }
-            if let Some(base) = base {
-                visitor.visit_expr(&visitor.thir()[base.base]);
-            }
-        }
-        PlaceTypeAscription { source, user_ty: _ } | ValueTypeAscription { source, user_ty: _ } => {
-            visitor.visit_expr(&visitor.thir()[source])
-        }
-        Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {}
-        Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal),
-        StaticRef { literal, def_id: _ } => visitor.visit_const(literal),
-        InlineAsm { ref operands, template: _, options: _, line_spans: _ } => {
-            for op in &**operands {
-                use InlineAsmOperand::*;
-                match op {
-                    In { expr, reg: _ }
-                    | Out { expr: Some(expr), reg: _, late: _ }
-                    | InOut { expr, reg: _, late: _ }
-                    | SymFn { expr } => visitor.visit_expr(&visitor.thir()[*expr]),
-                    SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
-                        visitor.visit_expr(&visitor.thir()[*in_expr]);
-                        if let Some(out_expr) = out_expr {
-                            visitor.visit_expr(&visitor.thir()[*out_expr]);
-                        }
-                    }
-                    Out { expr: None, reg: _, late: _ }
-                    | Const { value: _, span: _ }
-                    | SymStatic { def_id: _ } => {}
-                }
-            }
-        }
-        ThreadLocalRef(_) => {}
-        LlvmInlineAsm { ref outputs, ref inputs, asm: _ } => {
-            for &out_expr in &**outputs {
-                visitor.visit_expr(&visitor.thir()[out_expr]);
-            }
-            for &in_expr in &**inputs {
-                visitor.visit_expr(&visitor.thir()[in_expr]);
-            }
-        }
-        Yield { value } => visitor.visit_expr(&visitor.thir()[value]),
-    }
-}
-
-pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stmt<'tcx>) {
-    match &stmt.kind {
-        StmtKind::Expr { expr, scope: _ } => visitor.visit_expr(&visitor.thir()[*expr]),
-        StmtKind::Let {
-            initializer,
-            remainder_scope: _,
-            init_scope: _,
-            ref pattern,
-            lint_level: _,
-        } => {
-            if let Some(init) = initializer {
-                visitor.visit_expr(&visitor.thir()[*init]);
-            }
-            visitor.visit_pat(pattern);
-        }
-    }
-}
-
-pub fn walk_block<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, block: &Block) {
-    for &stmt in &*block.stmts {
-        visitor.visit_stmt(&visitor.thir()[stmt]);
-    }
-    if let Some(expr) = block.expr {
-        visitor.visit_expr(&visitor.thir()[expr]);
-    }
-}
-
-pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
-    match arm.guard {
-        Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
-        Some(Guard::IfLet(ref pat, expr)) => {
-            visitor.visit_pat(pat);
-            visitor.visit_expr(&visitor.thir()[expr]);
-        }
-        None => {}
-    }
-    visitor.visit_pat(&arm.pattern);
-    visitor.visit_expr(&visitor.thir()[arm.body]);
-}
-
-pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
-    use PatKind::*;
-    match pat.kind.as_ref() {
-        AscribeUserType { subpattern, ascription: _ }
-        | Deref { subpattern }
-        | Binding {
-            subpattern: Some(subpattern),
-            mutability: _,
-            mode: _,
-            var: _,
-            ty: _,
-            is_primary: _,
-            name: _,
-        } => visitor.visit_pat(&subpattern),
-        Binding { .. } | Wild => {}
-        Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
-            for subpattern in subpatterns {
-                visitor.visit_pat(&subpattern.pattern);
-            }
-        }
-        Constant { value } => visitor.visit_const(value),
-        Range(range) => {
-            visitor.visit_const(range.lo);
-            visitor.visit_const(range.hi);
-        }
-        Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
-            for subpattern in prefix {
-                visitor.visit_pat(&subpattern);
-            }
-            if let Some(pat) = slice {
-                visitor.visit_pat(pat);
-            }
-            for subpattern in suffix {
-                visitor.visit_pat(&subpattern);
-            }
-        }
-        Or { pats } => {
-            for pat in pats {
-                visitor.visit_pat(&pat);
-            }
-        }
-    };
-}
index 3cd4892402e4c36ef493d2a6ff1ffc152bfaba59..ffd7e3cd06bd266d1e797fb981811cfe1459cbe7 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_mir_dataflow"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index bfae09b7760a04672941a8c63d962fbe31ea2d03..72c4e27cbeabfbcffd5b98f98810512604e31d3f 100644 (file)
@@ -28,8 +28,8 @@
     on_lookup_result_bits,
 };
 pub use self::framework::{
-    fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, Forward,
-    GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
+    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
+    Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
     ResultsVisitable, ResultsVisitor,
 };
 
index cea465ea1ed9dc423045c5a80d5ffed630310173..407ba739463013ddb2346298efcc0774134141d9 100644 (file)
@@ -342,7 +342,7 @@ fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
             | Rvalue::AddressOf(..)
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
-            | Rvalue::NullaryOp(NullOp::SizeOf, _)
+            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
             | Rvalue::NullaryOp(NullOp::Box, _) => {
                 // This returns an rvalue with uninitialized contents. We can't
                 // move out of it here because it is an rvalue - assignments always
index 5e1a587b0ecead71635b3a70a71527e93106a133..bde4e215a2a61629d3ea8fef2261490fe8926cdf 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_mir_transform"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 855dcbc431b1eca3f57c50bfda93a1ac5e853d14..1abb64219f6e97dee0a68d16da9e8e761152ce26 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_middle::ty::layout;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::spec::abi::Abi;
+use rustc_target::spec::PanicStrategy;
 
 /// A pass that runs which is targeted at ensuring that codegen guarantees about
 /// unwinding are upheld for compilations of panic=abort programs.
@@ -82,10 +83,11 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                     };
                     layout::fn_can_unwind(tcx, flags, sig.abi())
                 }
-                TerminatorKind::Drop { .. }
-                | TerminatorKind::DropAndReplace { .. }
-                | TerminatorKind::Assert { .. }
-                | TerminatorKind::FalseUnwind { .. } => {
+                TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+                    tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
+                        && layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
+                }
+                TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
                     layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
                 }
                 _ => continue,
index 6043606c37957da13fb600d9926ccdb49181a21a..b9e3c058ad7ec355e98206308bc31bb0e368cc5b 100644 (file)
@@ -263,7 +263,7 @@ fn inject_counters(&'a mut self) {
         }
 
         if let Err(e) = result {
-            bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e)
+            bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message)
         };
 
         // Depending on current `debug_options()`, `alert_on_unused_expressions()` could panic, so
index 2ea2e06029d679176e20719eab21f281c361eaa3..cc525a4d6b91ca1a1ab9e491b4086c57a6c46885 100644 (file)
@@ -196,7 +196,11 @@ pub fn current_macro(&self) -> Option<Symbol> {
     /// body_span), returns the macro name symbol.
     pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
         if let Some(current_macro) = self.current_macro() {
-            if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt()
+            if self
+                .expn_span
+                .parent_callsite()
+                .unwrap_or_else(|| bug!("macro must have a parent"))
+                .ctxt()
                 == body_span.ctxt()
             {
                 return Some(current_macro);
index cc93fd482b5d49d4400e4d47b3a517dd1b346cdf..f5e8b65656a3ebe981bf8242e9f85caa97cf0373 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "coverage_test_macros"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 proc-macro = true
index 9a074c10ef405bf4c80e8a546f320134eeb6fafa..bfd0de85438d1044778c9e142601abf61317e64d 100644 (file)
@@ -76,7 +76,7 @@
 use rustc_const_eval::transform::check_consts;
 use rustc_const_eval::transform::promote_consts;
 use rustc_const_eval::transform::validate;
-use rustc_const_eval::transform::MirPass;
+pub use rustc_const_eval::transform::MirPass;
 use rustc_mir_dataflow::rustc_peek;
 
 pub fn provide(providers: &mut Providers) {
@@ -306,7 +306,6 @@ fn mir_promoted(
     // this point, before we steal the mir-const result.
     // Also this means promotion can rely on all const checks having been done.
     let _ = tcx.mir_const_qualif_opt_const_arg(def);
-    let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global());
     let mut body = tcx.mir_const(def).steal();
 
     let mut required_consts = Vec::new();
index 2f89b041c27b1f7062502f547ef5efbb840ec0fa..5848163af72fc22b0cc2d09f56f5f308e445852d 100644 (file)
@@ -92,14 +92,19 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                         // since their semantics depend on the value of overflow-checks flag used
                         // during codegen. Issue #35310.
                     }
-                    sym::size_of => {
+                    sym::size_of | sym::min_align_of => {
                         if let Some((destination, target)) = *destination {
                             let tp_ty = substs.type_at(0);
+                            let null_op = match intrinsic_name {
+                                sym::size_of => NullOp::SizeOf,
+                                sym::min_align_of => NullOp::AlignOf,
+                                _ => bug!("unexpected intrinsic"),
+                            };
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
                                     destination,
-                                    Rvalue::NullaryOp(NullOp::SizeOf, tp_ty),
+                                    Rvalue::NullaryOp(null_op, tp_ty),
                                 ))),
                             });
                             terminator.kind = TerminatorKind::Goto { target };
index 30de374a2d8221ddb5cbed5138302b15f45d2cac..a2cce9f1eda076e12fc6f2f43b0465a5c4e62507 100644 (file)
@@ -75,13 +75,11 @@ fn lower_slice_len_call<'tcx>(
                     let deref_arg = tcx.mk_place_deref(arg);
                     let r_value = Rvalue::Len(deref_arg);
                     let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
-                    let add_statement = Statement {
-                        kind: len_statement_kind,
-                        source_info: terminator.source_info.clone(),
-                    };
+                    let add_statement =
+                        Statement { kind: len_statement_kind, source_info: terminator.source_info };
 
                     // modify terminator into simple Goto
-                    let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() };
+                    let new_terminator_kind = TerminatorKind::Goto { target: *bb };
 
                     let patch = SliceLenPatchInformation { add_statement, new_terminator_kind };
 
index 25e3c52132cca69b59c30d44f719d9298bb07f47..d93ffa38c69066f40a5cced0b7bcf479b6993cea 100644 (file)
@@ -9,6 +9,10 @@
 
 impl<'tcx> MirPass<'tcx> for RemoveZsts {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        // Avoid query cycles (generators require optimized MIR for layout).
+        if tcx.type_of(body.source.def_id()).is_generator() {
+            return;
+        }
         let param_env = tcx.param_env(body.source.def_id());
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for block in basic_blocks.iter_mut() {
index e3cfd1d0afcd79c870dafeb5c8e61af6472afa7d..d6cd505cbb569d281ef85fb16cb49ef896071b00 100644 (file)
@@ -95,8 +95,6 @@ pub fn new(body: &'a mut Body<'tcx>) -> Self {
     pub fn simplify(mut self) {
         self.strip_nops();
 
-        let mut start = START_BLOCK;
-
         // Vec of the blocks that should be merged. We store the indices here, instead of the
         // statements itself to avoid moving the (relatively) large statements twice.
         // We do not push the statements directly into the target block (`bb`) as that is slower
@@ -105,8 +103,6 @@ pub fn simplify(mut self) {
         loop {
             let mut changed = false;
 
-            self.collapse_goto_chain(&mut start, &mut changed);
-
             for bb in self.basic_blocks.indices() {
                 if self.pred_count[bb] == 0 {
                     continue;
@@ -149,27 +145,6 @@ pub fn simplify(mut self) {
                 break;
             }
         }
-
-        if start != START_BLOCK {
-            debug_assert!(self.pred_count[START_BLOCK] == 0);
-            self.basic_blocks.swap(START_BLOCK, start);
-            self.pred_count.swap(START_BLOCK, start);
-
-            // pred_count == 1 if the start block has no predecessor _blocks_.
-            if self.pred_count[START_BLOCK] > 1 {
-                for (bb, data) in self.basic_blocks.iter_enumerated_mut() {
-                    if self.pred_count[bb] == 0 {
-                        continue;
-                    }
-
-                    for target in data.terminator_mut().successors_mut() {
-                        if *target == start {
-                            *target = START_BLOCK;
-                        }
-                    }
-                }
-            }
-        }
     }
 
     /// This function will return `None` if
index 350ae08877718e38fc0c561c676d306048fa148e..f812afe6b62ba9cd88c6e660c056f94abc9065c1 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_monomorphize"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 3c55a4b0a8fb1e52040d7a3e6055c2aeb47921d9..0f768b7819b5b67e35e6938626b5347e27588be3 100644 (file)
@@ -30,7 +30,7 @@ pub fn provide(providers: &mut Providers) {
 /// Determine which generic parameters are used by the function/method/closure represented by
 /// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
 /// indicates all parameters are used).
-#[instrument(skip(tcx))]
+#[instrument(level = "debug", skip(tcx))]
 fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
     if !tcx.sess.opts.debugging_opts.polymorphize {
         // If polymorphization disabled, then all parameters are used.
@@ -100,7 +100,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
 /// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
 /// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
 /// be `true` if the item that `unused_generic_params` was invoked on is a closure.
-#[instrument(skip(tcx, def_id, generics, unused_parameters))]
+#[instrument(level = "debug", skip(tcx, def_id, generics, unused_parameters))]
 fn mark_used_by_default_parameters<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
@@ -158,7 +158,7 @@ fn mark_used_by_default_parameters<'tcx>(
 
 /// Search the predicates on used generic parameters for any unused generic parameters, and mark
 /// those as used.
-#[instrument(skip(tcx, def_id))]
+#[instrument(level = "debug", skip(tcx, def_id))]
 fn mark_used_by_predicates<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
@@ -196,7 +196,7 @@ fn mark_used_by_predicates<'tcx>(
 
 /// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
 /// parameter which was unused.
-#[instrument(skip(tcx, generics))]
+#[instrument(level = "debug", skip(tcx, generics))]
 fn emit_unused_generic_params_error<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
@@ -241,7 +241,7 @@ struct MarkUsedGenericParams<'a, 'tcx> {
 impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
     /// Invoke `unused_generic_params` on a body contained within the current item (e.g.
     /// a closure, generator or constant).
-    #[instrument(skip(self, def_id, substs))]
+    #[instrument(level = "debug", skip(self, def_id, substs))]
     fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
         let unused = self.tcx.unused_generic_params(def_id);
         debug!(?self.unused_parameters, ?unused);
@@ -256,7 +256,7 @@ fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
-    #[instrument(skip(self, local))]
+    #[instrument(level = "debug", skip(self, local))]
     fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
         if local == Local::from_usize(1) {
             let def_kind = self.tcx.def_kind(self.def_id);
@@ -286,7 +286,7 @@ 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))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         if !c.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
@@ -319,7 +319,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         }
     }
 
-    #[instrument(skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         if !ty.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
@@ -361,7 +361,7 @@ fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
         Some(self.tcx)
     }
 
-    #[instrument(skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         if !c.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
@@ -379,7 +379,7 @@ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
         }
     }
 
-    #[instrument(skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         if !ty.potentially_has_param_types_or_consts() {
             return ControlFlow::CONTINUE;
index 1ca1a92252ea48c6f2189408f36e0cf0c2f4c6e2..1decaaa955f023075367e523b4e801eec49a2cb1 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_parse"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index aa6b424ce2b57ec167c85c7086471cc3165d62ec..cef5b3a226bff81a65f1fa69da5bdfc227e06a77 100644 (file)
@@ -3,7 +3,7 @@
 use std::iter::once;
 use std::ops::Range;
 
-use rustc_errors::{Applicability, Handler};
+use rustc_errors::{pluralize, Applicability, Handler};
 use rustc_lexer::unescape::{EscapeError, Mode};
 use rustc_span::{BytePos, Span};
 
@@ -49,24 +49,57 @@ pub(crate) fn emit_unescape_error(
                 .emit();
         }
         EscapeError::MoreThanOneChar => {
-            let (prefix, msg) = if mode.is_bytes() {
-                ("b", "if you meant to write a byte string literal, use double quotes")
-            } else {
-                ("", "if you meant to write a `str` literal, use double quotes")
-            };
+            use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
 
-            handler
-                .struct_span_err(
-                    span_with_quotes,
-                    "character literal may only contain one codepoint",
-                )
-                .span_suggestion(
+            let mut has_help = false;
+            let mut handler = handler.struct_span_err(
+                span_with_quotes,
+                "character literal may only contain one codepoint",
+            );
+
+            if lit.chars().skip(1).all(|c| is_combining_mark(c)) {
+                let escaped_marks =
+                    lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>();
+                handler.span_note(
+                    span,
+                    &format!(
+                        "this `{}` is followed by the combining mark{} `{}`",
+                        lit.chars().next().unwrap(),
+                        pluralize!(escaped_marks.len()),
+                        escaped_marks.join(""),
+                    ),
+                );
+                let normalized = lit.nfc().to_string();
+                if normalized.chars().count() == 1 {
+                    has_help = true;
+                    handler.span_suggestion(
+                        span,
+                        &format!(
+                            "consider using the normalized form `{}` of this character",
+                            normalized.chars().next().unwrap().escape_default()
+                        ),
+                        normalized,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+
+            if !has_help {
+                let (prefix, msg) = if mode.is_bytes() {
+                    ("b", "if you meant to write a byte string literal, use double quotes")
+                } else {
+                    ("", "if you meant to write a `str` literal, use double quotes")
+                };
+
+                handler.span_suggestion(
                     span_with_quotes,
                     msg,
                     format!("{}\"{}\"", prefix, lit),
                     Applicability::MachineApplicable,
-                )
-                .emit();
+                );
+            }
+
+            handler.emit();
         }
         EscapeError::EscapeOnlyChar => {
             let (c, char_span) = last_char();
index 08615e7be9ca25f44cf6638a530d56b80f3fa167..af41a99ada4dd57997756c1f318b3a38c79741c5 100644 (file)
@@ -131,7 +131,7 @@ fn maybe_source_file_to_parser(
     let mut parser = stream_to_parser(sess, stream, None);
     parser.unclosed_delims = unclosed_delims;
     if parser.token == token::Eof {
-        parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
+        parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
     }
 
     Ok(parser)
index 9f06bdcc135ba3d626d97fb418ffd18df84e859c..568682cc3e4e0498228dd4a1319ebc4ccf8a584b 100644 (file)
@@ -34,7 +34,7 @@ pub struct AttrWrapper {
 
 // This struct is passed around very frequently,
 // so make sure it doesn't accidentally get larger
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(AttrWrapper, 16);
 
 impl AttrWrapper {
index 94ca70d3f9578efa2020fb58d222cd6f8981cf80..708df5e46d4e22ef94dca8c3bdd49f61a8f53800 100644 (file)
@@ -1334,30 +1334,25 @@ pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
     pub(super) fn recover_parens_around_for_head(
         &mut self,
         pat: P<Pat>,
-        expr: &Expr,
         begin_paren: Option<Span>,
     ) -> P<Pat> {
         match (&self.token.kind, begin_paren) {
             (token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
                 self.bump();
 
-                let pat_str = self
-                    // Remove the `(` from the span of the pattern:
-                    .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
-                    .unwrap_or_else(|_| pprust::pat_to_string(&pat));
-
-                self.struct_span_err(self.prev_token.span, "unexpected closing `)`")
-                    .span_label(begin_par_sp, "opening `(`")
-                    .span_suggestion(
-                        begin_par_sp.to(self.prev_token.span),
-                        "remove parenthesis in `for` loop",
-                        format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
-                        // With e.g. `for (x) in y)` this would replace `(x) in y)`
-                        // with `x) in y)` which is syntactically invalid.
-                        // However, this is prevented before we get here.
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.struct_span_err(
+                    MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
+                    "unexpected parenthesis surrounding `for` loop head",
+                )
+                .multipart_suggestion(
+                    "remove parenthesis in `for` loop",
+                    vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
+                    // With e.g. `for (x) in y)` this would replace `(x) in y)`
+                    // with `x) in y)` which is syntactically invalid.
+                    // However, this is prevented before we get here.
+                    Applicability::MachineApplicable,
+                )
+                .emit();
 
                 // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
                 pat.and_then(|pat| match pat.kind {
@@ -1633,50 +1628,57 @@ pub(super) fn parameter_without_type(
         {
             let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
 
-            let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
-                PatKind::Ident(_, ident, _) => (
-                    ident,
-                    format!("self: {}", ident),
-                    format!("{}: TypeName", ident),
-                    format!("_: {}", ident),
-                ),
-                // Also catches `fn foo(&a)`.
-                PatKind::Ref(ref pat, mutab)
-                    if matches!(pat.clone().into_inner().kind, PatKind::Ident(..)) =>
-                {
-                    match pat.clone().into_inner().kind {
-                        PatKind::Ident(_, ident, _) => {
-                            let mutab = mutab.prefix_str();
-                            (
-                                ident,
-                                format!("self: &{}{}", mutab, ident),
-                                format!("{}: &{}TypeName", ident, mutab),
-                                format!("_: &{}{}", mutab, ident),
-                            )
+            let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
+                match pat.kind {
+                    PatKind::Ident(_, ident, _) => (
+                        ident,
+                        "self: ".to_string(),
+                        ": TypeName".to_string(),
+                        "_: ".to_string(),
+                        pat.span.shrink_to_lo(),
+                        pat.span.shrink_to_hi(),
+                        pat.span.shrink_to_lo(),
+                    ),
+                    // Also catches `fn foo(&a)`.
+                    PatKind::Ref(ref inner_pat, mutab)
+                        if matches!(inner_pat.clone().into_inner().kind, PatKind::Ident(..)) =>
+                    {
+                        match inner_pat.clone().into_inner().kind {
+                            PatKind::Ident(_, ident, _) => {
+                                let mutab = mutab.prefix_str();
+                                (
+                                    ident,
+                                    "self: ".to_string(),
+                                    format!("{}: &{}TypeName", ident, mutab),
+                                    "_: ".to_string(),
+                                    pat.span.shrink_to_lo(),
+                                    pat.span,
+                                    pat.span.shrink_to_lo(),
+                                )
+                            }
+                            _ => unreachable!(),
                         }
-                        _ => unreachable!(),
-                    }
-                }
-                _ => {
-                    // Otherwise, try to get a type and emit a suggestion.
-                    if let Some(ty) = pat.to_ty() {
-                        err.span_suggestion_verbose(
-                            pat.span,
-                            "explicitly ignore the parameter name",
-                            format!("_: {}", pprust::ty_to_string(&ty)),
-                            Applicability::MachineApplicable,
-                        );
-                        err.note(rfc_note);
                     }
+                    _ => {
+                        // Otherwise, try to get a type and emit a suggestion.
+                        if let Some(ty) = pat.to_ty() {
+                            err.span_suggestion_verbose(
+                                pat.span,
+                                "explicitly ignore the parameter name",
+                                format!("_: {}", pprust::ty_to_string(&ty)),
+                                Applicability::MachineApplicable,
+                            );
+                            err.note(rfc_note);
+                        }
 
-                    return None;
-                }
-            };
+                        return None;
+                    }
+                };
 
             // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
             if first_param {
                 err.span_suggestion(
-                    pat.span,
+                    self_span,
                     "if this is a `self` type, give it a parameter name",
                     self_sugg,
                     Applicability::MaybeIncorrect,
@@ -1686,14 +1688,14 @@ pub(super) fn parameter_without_type(
             // `fn foo(HashMap: TypeName<u32>)`.
             if self.token != token::Lt {
                 err.span_suggestion(
-                    pat.span,
+                    param_span,
                     "if this is a parameter name, give it a type",
                     param_sugg,
                     Applicability::HasPlaceholders,
                 );
             }
             err.span_suggestion(
-                pat.span,
+                type_span,
                 "if this is a type, explicitly ignore the parameter name",
                 type_sugg,
                 Applicability::MachineApplicable,
@@ -1948,7 +1950,19 @@ pub fn recover_const_arg(
         }
         match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
             Ok(expr) => {
-                if token::Comma == self.token.kind || self.token.kind.should_end_const_arg() {
+                // Find a mistake like `MyTrait<Assoc == S::Assoc>`.
+                if token::EqEq == snapshot.token.kind {
+                    err.span_suggestion(
+                        snapshot.token.span,
+                        "if you meant to use an associated type binding, replace `==` with `=`",
+                        "=".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    let value = self.mk_expr_err(start.to(expr.span));
+                    err.emit();
+                    return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
+                } else if token::Comma == self.token.kind || self.token.kind.should_end_const_arg()
+                {
                     // Avoid the following output by checking that we consumed a full const arg:
                     // help: expressions must be enclosed in braces to be used as const generic
                     //       arguments
index 05156745105a1c0a10b839720f00c8a957d153ef..c62ea66b693e3153940dd1dec6cb6dba7525a219 100644 (file)
@@ -1,9 +1,12 @@
 use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType};
+use super::{
+    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+};
 use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
+use ast::token::DelimToken;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::Spacing;
@@ -91,6 +94,8 @@ impl<'a> Parser<'a> {
     /// Parses an expression.
     #[inline]
     pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
+        self.current_closure.take();
+
         self.parse_expr_res(Restrictions::empty(), None)
     }
 
@@ -902,6 +907,12 @@ fn parse_dot_or_call_expr_with_(&mut self, mut e: P<Expr>, lo: Span) -> PResult<
         }
     }
 
+    fn look_ahead_type_ascription_as_field(&mut self) -> bool {
+        self.look_ahead(1, |t| t.is_ident())
+            && self.look_ahead(2, |t| t == &token::Colon)
+            && self.look_ahead(3, |t| t.can_begin_expr())
+    }
+
     fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
         match self.token.uninterpolate().kind {
             token::Ident(..) => self.parse_dot_suffix(base, lo),
@@ -1051,12 +1062,76 @@ fn parse_tuple_field_access_expr(
 
     /// Parse a function call expression, `expr(...)`.
     fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
-        let seq = self.parse_paren_expr_seq().map(|args| {
+        let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
+            && self.look_ahead_type_ascription_as_field()
+        {
+            Some((self.clone(), fun.kind.clone()))
+        } else {
+            None
+        };
+        let open_paren = self.token.span;
+
+        let mut seq = self.parse_paren_expr_seq().map(|args| {
             self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new())
         });
+        if let Some(expr) =
+            self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
+        {
+            return expr;
+        }
         self.recover_seq_parse_error(token::Paren, lo, seq)
     }
 
+    /// If we encounter a parser state that looks like the user has written a `struct` literal with
+    /// parentheses instead of braces, recover the parser state and provide suggestions.
+    fn maybe_recover_struct_lit_bad_delims(
+        &mut self,
+        lo: Span,
+        open_paren: Span,
+        seq: &mut PResult<'a, P<Expr>>,
+        snapshot: Option<(Self, ExprKind)>,
+    ) -> Option<P<Expr>> {
+        match (seq.as_mut(), snapshot) {
+            (Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
+                let name = pprust::path_to_string(&path);
+                snapshot.bump(); // `(`
+                match snapshot.parse_struct_fields(path.clone(), false, token::Paren) {
+                    Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
+                        // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
+                        // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
+                        *self = snapshot;
+                        let close_paren = self.prev_token.span;
+                        let span = lo.to(self.prev_token.span);
+                        err.cancel();
+                        self.struct_span_err(
+                            span,
+                            "invalid `struct` delimiters or `fn` call arguments",
+                        )
+                        .multipart_suggestion(
+                            &format!("if `{}` is a struct, use braces as delimiters", name),
+                            vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
+                            Applicability::MaybeIncorrect,
+                        )
+                        .multipart_suggestion(
+                            &format!("if `{}` is a function, use the arguments directly", name),
+                            fields
+                                .into_iter()
+                                .map(|field| (field.span.until(field.expr.span), String::new()))
+                                .collect(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                        return Some(self.mk_expr_err(span));
+                    }
+                    Ok(_) => {}
+                    Err(mut err) => err.emit(),
+                }
+            }
+            _ => {}
+        }
+        None
+    }
+
     /// Parse an indexing expression `expr[...]`.
     fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
         self.bump(); // `[`
@@ -1129,7 +1204,7 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
         } else if self.check(&token::BinOp(token::Or)) || self.check(&token::OrOr) {
             self.parse_closure_expr(attrs)
         } else if self.check(&token::OpenDelim(token::Bracket)) {
-            self.parse_array_or_repeat_expr(attrs)
+            self.parse_array_or_repeat_expr(attrs, token::Bracket)
         } else if self.check_path() {
             self.parse_path_start_expr(attrs)
         } else if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) {
@@ -1247,11 +1322,15 @@ fn parse_tuple_parens_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         self.maybe_recover_from_bad_qpath(expr, true)
     }
 
-    fn parse_array_or_repeat_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
+    fn parse_array_or_repeat_expr(
+        &mut self,
+        attrs: AttrVec,
+        close_delim: token::DelimToken,
+    ) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
-        self.bump(); // `[`
+        self.bump(); // `[` or other open delim
 
-        let close = &token::CloseDelim(token::Bracket);
+        let close = &token::CloseDelim(close_delim);
         let kind = if self.eat(close) {
             // Empty vector
             ExprKind::Array(Vec::new())
@@ -1677,6 +1756,46 @@ pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
         }
     }
 
+    fn is_array_like_block(&mut self) -> bool {
+        self.look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_)))
+            && self.look_ahead(2, |t| t == &token::Comma)
+            && self.look_ahead(3, |t| t.can_begin_expr())
+    }
+
+    /// Emits a suggestion if it looks like the user meant an array but
+    /// accidentally used braces, causing the code to be interpreted as a block
+    /// expression.
+    fn maybe_suggest_brackets_instead_of_braces(
+        &mut self,
+        lo: Span,
+        attrs: AttrVec,
+    ) -> Option<P<Expr>> {
+        let mut snapshot = self.clone();
+        match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
+            Ok(arr) => {
+                let hi = snapshot.prev_token.span;
+                self.struct_span_err(
+                    arr.span,
+                    "this code is interpreted as a block expression, not an array",
+                )
+                .multipart_suggestion(
+                    "try using [] instead of {}",
+                    vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
+                    Applicability::MaybeIncorrect,
+                )
+                .note("to define an array, one would use square brackets instead of curly braces")
+                .emit();
+
+                *self = snapshot;
+                Some(self.mk_expr_err(arr.span))
+            }
+            Err(mut e) => {
+                e.cancel();
+                None
+            }
+        }
+    }
+
     /// Parses a block or unsafe block.
     pub(super) fn parse_block_expr(
         &mut self,
@@ -1685,6 +1804,12 @@ pub(super) fn parse_block_expr(
         blk_mode: BlockCheckMode,
         mut attrs: AttrVec,
     ) -> PResult<'a, P<Expr>> {
+        if self.is_array_like_block() {
+            if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo, attrs.clone()) {
+                return Ok(arr);
+            }
+        }
+
         if let Some(label) = opt_label {
             self.sess.gated_spans.gate(sym::label_break_value, label.ident.span);
         }
@@ -1736,7 +1861,7 @@ fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
         let capture_clause = self.parse_capture_clause()?;
         let decl = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_token.span;
-        let body = match decl.output {
+        let mut body = match decl.output {
             FnRetTy::Default(_) => {
                 let restrictions = self.restrictions - Restrictions::STMT_EXPR;
                 self.parse_expr_res(restrictions, None)?
@@ -1753,11 +1878,28 @@ fn parse_closure_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
             self.sess.gated_spans.gate(sym::async_closure, span);
         }
 
-        Ok(self.mk_expr(
+        if self.token.kind == TokenKind::Semi && self.token_cursor.frame.delim == DelimToken::Paren
+        {
+            // It is likely that the closure body is a block but where the
+            // braces have been removed. We will recover and eat the next
+            // statements later in the parsing process.
+            body = self.mk_expr_err(body.span);
+        }
+
+        let body_span = body.span;
+
+        let closure = self.mk_expr(
             lo.to(body.span),
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
             attrs,
-        ))
+        );
+
+        // Disable recovery for closure body
+        let spans =
+            ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
+        self.current_closure = Some(spans);
+
+        Ok(closure)
     }
 
     /// Parses an optional `move` prefix to a closure-like construct.
@@ -1950,7 +2092,7 @@ fn parse_for_expr(
         self.check_for_for_in_in_typo(self.prev_token.span);
         let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
 
-        let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren);
+        let pat = self.recover_parens_around_for_head(pat, begin_paren);
 
         let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
@@ -2352,14 +2494,12 @@ fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) {
             .emit();
     }
 
-    /// Precondition: already parsed the '{'.
-    pub(super) fn parse_struct_expr(
+    pub(super) fn parse_struct_fields(
         &mut self,
-        qself: Option<ast::QSelf>,
         pth: ast::Path,
-        attrs: AttrVec,
         recover: bool,
-    ) -> PResult<'a, P<Expr>> {
+        close_delim: token::DelimToken,
+    ) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
         let mut fields = Vec::new();
         let mut base = ast::StructRest::None;
         let mut recover_async = false;
@@ -2371,11 +2511,11 @@ pub(super) fn parse_struct_expr(
             e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
         };
 
-        while self.token != token::CloseDelim(token::Brace) {
+        while self.token != token::CloseDelim(close_delim) {
             if self.eat(&token::DotDot) {
                 let exp_span = self.prev_token.span;
                 // We permit `.. }` on the left-hand side of a destructuring assignment.
-                if self.check(&token::CloseDelim(token::Brace)) {
+                if self.check(&token::CloseDelim(close_delim)) {
                     self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span);
                     base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi());
                     break;
@@ -2416,7 +2556,7 @@ pub(super) fn parse_struct_expr(
                 }
             };
 
-            match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) {
+            match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
                 Ok(_) => {
                     if let Some(f) = parsed_field.or(recovery_field) {
                         // Only include the field if there's no parse error for the field name.
@@ -2447,8 +2587,21 @@ pub(super) fn parse_struct_expr(
                 }
             }
         }
+        Ok((fields, base, recover_async))
+    }
 
-        let span = pth.span.to(self.token.span);
+    /// Precondition: already parsed the '{'.
+    pub(super) fn parse_struct_expr(
+        &mut self,
+        qself: Option<ast::QSelf>,
+        pth: ast::Path,
+        attrs: AttrVec,
+        recover: bool,
+    ) -> PResult<'a, P<Expr>> {
+        let lo = pth.span;
+        let (fields, base, recover_async) =
+            self.parse_struct_fields(pth.clone(), recover, token::Brace)?;
+        let span = lo.to(self.token.span);
         self.expect(&token::CloseDelim(token::Brace))?;
         let expr = if recover_async {
             ExprKind::Err
index 10c73fd64bc198cece7158a1ea964629b8d985d8..0e2222bf84093913d3bfc926621130452c7ac6fd 100644 (file)
@@ -493,7 +493,20 @@ fn parse_item_impl(
         let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
         {
             let span = self.prev_token.span.between(self.token.span);
-            self.struct_span_err(span, "missing trait in a trait impl").emit();
+            self.struct_span_err(span, "missing trait in a trait impl")
+                .span_suggestion(
+                    span,
+                    "add a trait here",
+                    " Trait ".into(),
+                    Applicability::HasPlaceholders,
+                )
+                .span_suggestion(
+                    span.to(self.token.span),
+                    "for an inherent impl, drop this `for`",
+                    "".into(),
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
             P(Ty {
                 kind: TyKind::Path(None, err_path(span)),
                 span,
@@ -1234,7 +1247,7 @@ fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
         Ok((class_name, ItemKind::Union(vdata, generics)))
     }
 
-    pub(super) fn parse_record_struct_body(
+    fn parse_record_struct_body(
         &mut self,
         adt_ty: &str,
     ) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
@@ -1468,28 +1481,22 @@ fn parse_name_and_ty(
     fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
         let (ident, is_raw) = self.ident_or_err()?;
         if !is_raw && ident.is_reserved() {
-            if ident.name == kw::Underscore {
-                self.sess.gated_spans.gate(sym::unnamed_fields, lo);
+            let err = if self.check_fn_front_matter(false) {
+                // We use `parse_fn` to get a span for the function
+                if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
+                    db.delay_as_bug();
+                }
+                let mut err = self.struct_span_err(
+                    lo.to(self.prev_token.span),
+                    &format!("functions are not allowed in {} definitions", adt_ty),
+                );
+                err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
+                err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+                err
             } else {
-                let err = if self.check_fn_front_matter(false) {
-                    // We use `parse_fn` to get a span for the function
-                    if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
-                        db.delay_as_bug();
-                    }
-                    let mut err = self.struct_span_err(
-                        lo.to(self.prev_token.span),
-                        &format!("functions are not allowed in {} definitions", adt_ty),
-                    );
-                    err.help(
-                        "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
-                    );
-                    err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                    err
-                } else {
-                    self.expected_ident_found()
-                };
-                return Err(err);
-            }
+                self.expected_ident_found()
+            };
+            return Err(err);
         }
         self.bump();
         Ok(ident)
index c4419e995edac84940900418d87186aecdb89235..5c701fefd17de95b0d95dfaeaa64f625f61f27e2 100644 (file)
@@ -142,6 +142,17 @@ pub struct Parser<'a> {
     /// If present, this `Parser` is not parsing Rust code but rather a macro call.
     subparser_name: Option<&'static str>,
     capture_state: CaptureState,
+    /// This allows us to recover when the user forget to add braces around
+    /// multiple statements in the closure body.
+    pub current_closure: Option<ClosureSpans>,
+}
+
+/// Stores span informations about a closure.
+#[derive(Clone)]
+pub struct ClosureSpans {
+    pub whole_closure: Span,
+    pub closing_pipe: Span,
+    pub body: Span,
 }
 
 /// Indicates a range of tokens that should be replaced by
@@ -440,6 +451,7 @@ pub fn new(
                 replace_ranges: Vec::new(),
                 inner_attr_ranges: Default::default(),
             },
+            current_closure: None,
         };
 
         // Make parser point to the first token.
@@ -761,8 +773,11 @@ fn parse_seq_to_before_tokens<T>(
                     first = false;
                 } else {
                     match self.expect(t) {
-                        Ok(false) => {}
+                        Ok(false) => {
+                            self.current_closure.take();
+                        }
                         Ok(true) => {
+                            self.current_closure.take();
                             recovered = true;
                             break;
                         }
@@ -770,10 +785,29 @@ fn parse_seq_to_before_tokens<T>(
                             let sp = self.prev_token.span.shrink_to_hi();
                             let token_str = pprust::token_kind_to_string(t);
 
-                            // Attempt to keep parsing if it was a similar separator.
-                            if let Some(ref tokens) = t.similar_tokens() {
-                                if tokens.contains(&self.token.kind) && !unclosed_delims {
-                                    self.bump();
+                            match self.current_closure.take() {
+                                Some(closure_spans) if self.token.kind == TokenKind::Semi => {
+                                    // Finding a semicolon instead of a comma
+                                    // after a closure body indicates that the
+                                    // closure body may be a block but the user
+                                    // forgot to put braces around its
+                                    // statements.
+
+                                    self.recover_missing_braces_around_closure_body(
+                                        closure_spans,
+                                        expect_err,
+                                    )?;
+
+                                    continue;
+                                }
+
+                                _ => {
+                                    // Attempt to keep parsing if it was a similar separator.
+                                    if let Some(ref tokens) = t.similar_tokens() {
+                                        if tokens.contains(&self.token.kind) && !unclosed_delims {
+                                            self.bump();
+                                        }
+                                    }
                                 }
                             }
 
@@ -839,6 +873,65 @@ fn parse_seq_to_before_tokens<T>(
         Ok((v, trailing, recovered))
     }
 
+    fn recover_missing_braces_around_closure_body(
+        &mut self,
+        closure_spans: ClosureSpans,
+        mut expect_err: DiagnosticBuilder<'_>,
+    ) -> PResult<'a, ()> {
+        let initial_semicolon = self.token.span;
+
+        while self.eat(&TokenKind::Semi) {
+            let _ = self.parse_stmt(ForceCollect::Yes)?;
+        }
+
+        expect_err.set_primary_message(
+            "closure bodies that contain statements must be surrounded by braces",
+        );
+
+        let preceding_pipe_span = closure_spans.closing_pipe;
+        let following_token_span = self.token.span;
+
+        let mut first_note = MultiSpan::from(vec![initial_semicolon]);
+        first_note.push_span_label(
+            initial_semicolon,
+            "this `;` turns the preceding closure into a statement".to_string(),
+        );
+        first_note.push_span_label(
+            closure_spans.body,
+            "this expression is a statement because of the trailing semicolon".to_string(),
+        );
+        expect_err.span_note(first_note, "statement found outside of a block");
+
+        let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]);
+        second_note.push_span_label(
+            closure_spans.whole_closure,
+            "this is the parsed closure...".to_string(),
+        );
+        second_note.push_span_label(
+            following_token_span,
+            "...but likely you meant the closure to end here".to_string(),
+        );
+        expect_err.span_note(second_note, "the closure body may be incorrectly delimited");
+
+        expect_err.set_span(vec![preceding_pipe_span, following_token_span]);
+
+        let opening_suggestion_str = " {".to_string();
+        let closing_suggestion_str = "}".to_string();
+
+        expect_err.multipart_suggestion(
+            "try adding braces",
+            vec![
+                (preceding_pipe_span.shrink_to_hi(), opening_suggestion_str),
+                (following_token_span.shrink_to_lo(), closing_suggestion_str),
+            ],
+            Applicability::MaybeIncorrect,
+        );
+
+        expect_err.emit();
+
+        Ok(())
+    }
+
     /// Parses a sequence, not including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
index 25dcb4a112de1c7e030498a7167e97be22526055..9ec6effeb4e03a9e2ed2368204ed75511a38eb3d 100644 (file)
@@ -155,17 +155,20 @@ fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResu
 
         let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
 
-        let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
-        {
-            StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
-        } else {
-            // Since none of the above applied, this is an expression statement macro.
-            let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
-            let e = self.maybe_recover_from_bad_qpath(e, true)?;
-            let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
-            StmtKind::Expr(e)
-        };
+        let kind =
+            if (delim == token::Brace && self.token != token::Dot && self.token != token::Question)
+                || self.token == token::Semi
+                || self.token == token::Eof
+            {
+                StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
+            } else {
+                // Since none of the above applied, this is an expression statement macro.
+                let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
+                let e = self.maybe_recover_from_bad_qpath(e, true)?;
+                let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+                let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+                StmtKind::Expr(e)
+            };
         Ok(self.mk_stmt(lo.to(hi), kind))
     }
 
index 299fc916ac97fa7802b2f6a6865877dc8a0744e7..98400372c36a6576e9c90b8350f2d430d52a6a20 100644 (file)
@@ -226,19 +226,6 @@ fn parse_ty_common(
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
-        } else if self.token.is_keyword(kw::Union)
-            && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
-        {
-            self.bump();
-            let (fields, recovered) = self.parse_record_struct_body("union")?;
-            let span = lo.to(self.prev_token.span);
-            self.sess.gated_spans.gate(sym::unnamed_fields, span);
-            TyKind::AnonymousUnion(fields, recovered)
-        } else if self.eat_keyword(kw::Struct) {
-            let (fields, recovered) = self.parse_record_struct_body("struct")?;
-            let span = lo.to(self.prev_token.span);
-            self.sess.gated_spans.gate(sym::unnamed_fields, span);
-            TyKind::AnonymousStruct(fields, recovered)
         } else if self.is_explicit_dyn_type() {
             self.parse_dyn_ty(&mut impl_dyn_multi)?
         } else if self.eat_lt() {
index 7b77560717e139509bdc523dd2a8a686ecbc02c5..aa1714e820f4862a035ce10a11946245267d060c 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_parse_format"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 rustc_span = { path = "../rustc_span" }
index bf1e52cd9a8ad4a18eb567de9418cba1e295e027..39e578bce7ef67eecb9287da9fc56f77770bd800 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_passes"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 tracing = "0.1"
index 25ad00aaf1f753caa8f98f37224d898d5e1528ee..0a3093757166afee7641ddea25449c5322b27b17 100644 (file)
@@ -239,7 +239,69 @@ fn mark_live_symbols(&mut self) {
         }
     }
 
+    /// Automatically generated items marked with `rustc_trivial_field_reads`
+    /// will be ignored for the purposes of dead code analysis (see PR #85200
+    /// for discussion).
+    fn should_ignore_item(&self, def_id: DefId) -> bool {
+        if !self.tcx.has_attr(def_id, sym::automatically_derived)
+            && !self
+                .tcx
+                .impl_of_method(def_id)
+                .map_or(false, |impl_id| self.tcx.has_attr(impl_id, sym::automatically_derived))
+        {
+            return false;
+        }
+
+        let has_attr = |def_id| self.tcx.has_attr(def_id, sym::rustc_trivial_field_reads);
+
+        if has_attr(def_id) {
+            return true;
+        }
+
+        if let Some(impl_of) = self.tcx.impl_of_method(def_id) {
+            if has_attr(impl_of) {
+                return true;
+            }
+
+            if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) {
+                if has_attr(trait_of) {
+                    return true;
+                }
+
+                if let Some(method_ident) = self.tcx.opt_item_name(def_id) {
+                    if let Some(trait_method) = self
+                        .tcx
+                        .associated_items(trait_of)
+                        .find_by_name_and_kind(self.tcx, method_ident, ty::AssocKind::Fn, trait_of)
+                    {
+                        if has_attr(trait_method.def_id) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        } else if let Some(trait_of) = self.tcx.trait_of_item(def_id) {
+            if has_attr(trait_of) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     fn visit_node(&mut self, node: Node<'tcx>) {
+        if let Some(item_def_id) = match node {
+            Node::Item(hir::Item { def_id, .. })
+            | Node::ForeignItem(hir::ForeignItem { def_id, .. })
+            | Node::TraitItem(hir::TraitItem { def_id, .. })
+            | Node::ImplItem(hir::ImplItem { def_id, .. }) => Some(def_id.to_def_id()),
+            _ => None,
+        } {
+            if self.should_ignore_item(item_def_id) {
+                return;
+            }
+        }
+
         let had_repr_c = self.repr_has_repr_c;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
         let had_pub_visibility = self.pub_visibility;
index 18f61c6e1c1a787df5b6733e881d0db950c4f3f2..0e60ca9f900107a011ecfaa229c220b298de45b1 100644 (file)
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
+use rustc_data_structures::sync::Lock;
 use rustc_hir as hir;
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::intravisit;
@@ -18,9 +18,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
     let errors = Lock::new(Vec::new());
     let hir_map = tcx.hir();
 
-    par_iter(&hir_map.krate().modules).for_each(|(&module_id, _)| {
+    hir_map.par_for_each_module(|module_id| {
         hir_map
-            .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors });
+            .visit_item_likes_in_module(module_id, &mut OuterVisitor { hir_map, errors: &errors })
     });
 
     let errors = errors.into_inner();
@@ -163,14 +163,14 @@ fn visit_id(&mut self, hir_id: HirId) {
         self.hir_ids_seen.insert(hir_id.local_id);
     }
 
-    fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef<'hir>) {
+    fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) {
         // Explicitly do nothing here. ImplItemRefs contain hir::Visibility
         // values that actually belong to an ImplItem instead of the ItemKind::Impl
         // we are currently in. So for those it's correct that they have a
         // different owner.
     }
 
-    fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef<'hir>) {
+    fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef) {
         // Explicitly do nothing here. ForeignItemRefs contain hir::Visibility
         // values that actually belong to an ForeignItem instead of the ItemKind::ForeignMod
         // we are currently in. So for those it's correct that they have a
index ab9bfea96943f3eafe4505a4c7660d61bdfdf205..0d7abeba1a703c003cfbb13c05eb276d7c4c76b8 100644 (file)
@@ -775,7 +775,7 @@ fn propagate_through_block(&mut self, blk: &hir::Block<'_>, succ: LiveNode) -> L
         if blk.targeted_by_break {
             self.break_ln.insert(blk.hir_id, succ);
         }
-        let succ = self.propagate_through_opt_expr(blk.expr.as_deref(), succ);
+        let succ = self.propagate_through_opt_expr(blk.expr, succ);
         blk.stmts.iter().rev().fold(succ, |succ, stmt| self.propagate_through_stmt(stmt, succ))
     }
 
@@ -796,7 +796,7 @@ fn propagate_through_stmt(&mut self, stmt: &hir::Stmt<'_>, succ: LiveNode) -> Li
                 // initialization, which is mildly more complex than checking
                 // once at the func header but otherwise equivalent.
 
-                let succ = self.propagate_through_opt_expr(local.init.as_deref(), succ);
+                let succ = self.propagate_through_opt_expr(local.init, succ);
                 self.define_bindings_in_pat(&local.pat, succ)
             }
             hir::StmtKind::Item(..) => succ,
index 08702cad41c8b92b5e0a80676f16dd22d6e5b6c0..5fc8e230d72a3eba67aca78d8a258115f9d21e31 100644 (file)
@@ -812,7 +812,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
         resolve_expr(self, ex);
     }
     fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
-        resolve_local(self, Some(&l.pat), l.init.as_deref());
+        resolve_local(self, Some(&l.pat), l.init);
     }
 }
 
index b7e43b7785da602a170632beddb3ad53f0083155..d7c354aeb490f6accc78a15593b84410dc3655f5 100644 (file)
@@ -929,6 +929,16 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
     let declared_lib_features = &tcx.features().declared_lib_features;
     let mut remaining_lib_features = FxHashMap::default();
     for (feature, span) in declared_lib_features {
+        if !tcx.sess.opts.unstable_features.is_nightly_build() {
+            struct_span_err!(
+                tcx.sess,
+                *span,
+                E0554,
+                "`#![feature]` may not be used on the {} release channel",
+                env!("CFG_RELEASE_CHANNEL")
+            )
+            .emit();
+        }
         if remaining_lib_features.contains_key(&feature) {
             // Warn if the user enables a lib feature multiple times.
             duplicate_feature_err(tcx.sess, *span, *feature);
index c8eaca0703cb5b176968e4db1a6badb5634746f3..4e666e7e93d530faff9ff5e4797065376e05c45a 100644 (file)
@@ -2,7 +2,7 @@
 name = "rustc_plugin_impl"
 version = "0.0.0"
 build = false
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 6ac2915c3452688b40b1d98ac57f040b10a8f486..d952e288a6477c46864dde961e2999dca16bf557 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_privacy"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 rustc_middle = { path = "../rustc_middle" }
index 35e25e52dc5f9f1e2fc12b492055eff4eeb9dbd3..e14f758ddae79662db51d039b80d2cff40985112 100644 (file)
@@ -19,8 +19,8 @@
 use rustc_middle::bug;
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::mir::abstract_const::Node as ACNode;
 use rustc_middle::span_bug;
+use rustc_middle::thir::abstract_const::Node as ACNode;
 use rustc_middle::ty::fold::TypeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -743,7 +743,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             }
             hir::ItemKind::Impl(ref impl_) => {
                 for impl_item_ref in impl_.items {
-                    if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
+                    if impl_.of_trait.is_some()
+                        || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public
+                    {
                         self.update(impl_item_ref.id.def_id, item_level);
                     }
                 }
@@ -768,7 +770,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             }
             hir::ItemKind::ForeignMod { items, .. } => {
                 for foreign_item in items {
-                    if foreign_item.vis.node.is_pub() {
+                    if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public {
                         self.update(foreign_item.id.def_id, item_level);
                     }
                 }
@@ -1678,7 +1680,10 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
                     for impl_item_ref in impl_.items {
-                        if self.item_is_public(impl_item_ref.id.def_id, &impl_item_ref.vis) {
+                        if self.access_levels.is_reachable(impl_item_ref.id.def_id)
+                            || self.tcx.visibility(impl_item_ref.id.def_id)
+                                == ty::Visibility::Public
+                        {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
                                 AssocItemKind::Const => {
index 7c8dbe34240e215dd639aab75e28d50b6a3b91c5..89df3d4674b6b363cc471fe89329292966f3329d 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_query_impl"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 42e8b4023cfad489c219d106031baaf804cfdc79..563a3cf14382c74ad8ef7d094be0a9677cd12ed3 100644 (file)
@@ -449,3 +449,25 @@ fn default_span(&self, _tcx: TyCtxt<'_>) -> Span {
         DUMMY_SP
     }
 }
+
+impl<'tcx> Key for (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+
+    fn default_span(&self, _: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+}
+
+impl<'tcx> Key for (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>) {
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        self.0.default_span(tcx)
+    }
+}
index 5c2803c67e73fca87c75741741946820689356e2..d8cff0bd1880f898cd0d25da893d5b475c5bcd5c 100644 (file)
@@ -1,14 +1,15 @@
 use crate::QueryCtxt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell, RwLock};
+use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
+use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::mir::{self, interpret};
+use rustc_middle::thir;
 use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::dep_graph::DepContext;
@@ -23,8 +24,7 @@
 };
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::CachingSourceMapView;
-use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP};
-use std::collections::hash_map::Entry;
+use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
 use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@@ -33,6 +33,7 @@
 const TAG_FULL_SPAN: u8 = 0;
 // A partial span with no location information, encoded only with a `SyntaxContext`
 const TAG_PARTIAL_SPAN: u8 = 1;
+const TAG_RELATIVE_SPAN: u8 = 2;
 
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
@@ -49,8 +50,6 @@ pub struct OnDiskCache<'sess> {
     // session.
     current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>,
 
-    cnum_map: OnceCell<UnhashMap<StableCrateId, CrateNum>>,
-
     source_map: &'sess SourceMap,
     file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>,
 
@@ -85,27 +84,11 @@ pub struct OnDiskCache<'sess> {
     expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
     // Additional information used when decoding hygiene data.
     hygiene_context: HygieneDecodeContext,
-    // Maps `DefPathHash`es to their `RawDefId`s from the *previous*
+    // Maps `ExpnHash`es to their raw value from the *previous*
     // compilation session. This is used as an initial 'guess' when
-    // we try to map a `DefPathHash` to its `DefId` in the current compilation
-    // session.
-    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
-    // Likewise for ExpnId.
+    // we try to map an `ExpnHash` to its value in the current
+    // compilation session.
     foreign_expn_data: UnhashMap<ExpnHash, u32>,
-
-    // The *next* compilation sessison's `foreign_def_path_hashes` - at
-    // the end of our current compilation session, this will get written
-    // out to the `foreign_def_path_hashes` field of the `Footer`, which
-    // will become `foreign_def_path_hashes` of the next compilation session.
-    // This stores any `DefPathHash` that we may need to map to a `DefId`
-    // during the next compilation session.
-    latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
-
-    // Caches all lookups of `DefPathHashes`, both for local and foreign
-    // definitions. A definition from the previous compilation session
-    // may no longer exist in the current compilation session, so
-    // we use `Option<DefId>` so that we can cache a lookup failure.
-    def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
 }
 
 // This type is used only for serialization and deserialization.
@@ -120,7 +103,6 @@ struct Footer {
     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
     // See `OnDiskCache.expn_data`
     expn_data: UnhashMap<ExpnHash, AbsoluteBytePos>,
-    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
     foreign_expn_data: UnhashMap<ExpnHash, u32>,
 }
 
@@ -143,19 +125,6 @@ fn to_usize(self) -> usize {
     }
 }
 
-/// Represents a potentially invalid `DefId`. This is used during incremental
-/// compilation to represent a `DefId` from the *previous* compilation session,
-/// which may no longer be valid. This is used to help map a `DefPathHash`
-/// to a `DefId` in the current compilation session.
-#[derive(Encodable, Decodable, Copy, Clone, Debug)]
-crate struct RawDefId {
-    // We deliberately do not use `CrateNum` and `DefIndex`
-    // here, since a crate/index from the previous compilation
-    // session may no longer exist.
-    pub krate: u32,
-    pub index: u32,
-}
-
 /// An `EncodedSourceFileId` is the same as a `StableSourceFileId` except that
 /// the source crate is represented as a [StableCrateId] instead of as a
 /// `CrateNum`. This way `EncodedSourceFileId` can be encoded and decoded
@@ -168,8 +137,8 @@ struct EncodedSourceFileId {
 }
 
 impl EncodedSourceFileId {
-    fn translate(&self, cnum_map: &UnhashMap<StableCrateId, CrateNum>) -> StableSourceFileId {
-        let cnum = cnum_map[&self.stable_crate_id];
+    fn translate(&self, tcx: TyCtxt<'_>) -> StableSourceFileId {
+        let cnum = tcx.stable_crate_id_to_crate_num(self.stable_crate_id);
         StableSourceFileId { file_name_hash: self.file_name_hash, cnum }
     }
 
@@ -209,7 +178,6 @@ fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
             serialized_data: RwLock::new(Some(data)),
             file_index_to_stable_id: footer.file_index_to_stable_id,
             file_index_to_file: Default::default(),
-            cnum_map: OnceCell::new(),
             source_map: sess.source_map(),
             current_side_effects: Default::default(),
             query_result_index: footer.query_result_index.into_iter().collect(),
@@ -219,9 +187,6 @@ fn new(sess: &'sess Session, data: Mmap, start_pos: usize) -> Self {
             expn_data: footer.expn_data,
             foreign_expn_data: footer.foreign_expn_data,
             hygiene_context: Default::default(),
-            foreign_def_path_hashes: footer.foreign_def_path_hashes,
-            latest_foreign_def_path_hashes: Default::default(),
-            def_path_hash_to_def_id_cache: Default::default(),
         }
     }
 
@@ -230,7 +195,6 @@ fn new_empty(source_map: &'sess SourceMap) -> Self {
             serialized_data: RwLock::new(None),
             file_index_to_stable_id: Default::default(),
             file_index_to_file: Default::default(),
-            cnum_map: OnceCell::new(),
             source_map,
             current_side_effects: Default::default(),
             query_result_index: Default::default(),
@@ -240,9 +204,6 @@ fn new_empty(source_map: &'sess SourceMap) -> Self {
             expn_data: UnhashMap::default(),
             foreign_expn_data: UnhashMap::default(),
             hygiene_context: Default::default(),
-            foreign_def_path_hashes: Default::default(),
-            latest_foreign_def_path_hashes: Default::default(),
-            def_path_hash_to_def_id_cache: Default::default(),
         }
     }
 
@@ -252,13 +213,6 @@ fn new_empty(source_map: &'sess SourceMap) -> Self {
     /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be
     /// deleted, hence we won't be able to refer to its memmapped data.
     fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) {
-        // Register any dep nodes that we reused from the previous session,
-        // but didn't `DepNode::construct` in this session. This ensures
-        // that their `DefPathHash` to `RawDefId` mappings are registered
-        // in 'latest_foreign_def_path_hashes' if necessary, since that
-        // normally happens in `DepNode::construct`.
-        tcx.dep_graph.register_reused_dep_nodes(tcx);
-
         // Load everything into memory so we can write it out to the on-disk
         // cache. The vast majority of cacheable query results should already
         // be in memory, so this should be a cheap operation.
@@ -292,7 +246,6 @@ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileE
                 (file_to_file_index, file_index_to_stable_id)
             };
 
-            let latest_foreign_def_path_hashes = self.latest_foreign_def_path_hashes.lock().clone();
             let hygiene_encode_context = HygieneEncodeContext::default();
 
             let mut encoder = CacheEncoder {
@@ -304,7 +257,6 @@ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileE
                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
                 file_to_file_index,
                 hygiene_context: &hygiene_encode_context,
-                latest_foreign_def_path_hashes,
             };
 
             // Encode query results.
@@ -381,9 +333,6 @@ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileE
                 },
             )?;
 
-            let foreign_def_path_hashes =
-                std::mem::take(&mut encoder.latest_foreign_def_path_hashes);
-
             // `Encode the file footer.
             let footer_pos = encoder.position() as u64;
             encoder.encode_tagged(
@@ -396,7 +345,6 @@ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileE
                     syntax_contexts,
                     expn_data,
                     foreign_expn_data,
-                    foreign_def_path_hashes,
                 },
             )?;
 
@@ -411,80 +359,21 @@ fn serialize<'tcx>(&self, tcx: TyCtxt<'tcx>, encoder: &mut FileEncoder) -> FileE
         })
     }
 
-    fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> Option<DefId> {
-        let mut cache = self.def_path_hash_to_def_id_cache.lock();
-        match cache.entry(hash) {
-            Entry::Occupied(e) => *e.get(),
-            Entry::Vacant(e) => {
-                debug!("def_path_hash_to_def_id({:?})", hash);
-                // Check if the `DefPathHash` corresponds to a definition in the current
-                // crate
-                if let Some(def_id) =
-                    tcx.definitions_untracked().local_def_path_hash_to_def_id(hash)
-                {
-                    let def_id = def_id.to_def_id();
-                    e.insert(Some(def_id));
-                    return Some(def_id);
-                }
-                // This `raw_def_id` represents the `DefId` of this `DefPathHash` in
-                // the *previous* compliation session. The `DefPathHash` includes the
-                // owning crate, so if the corresponding definition still exists in the
-                // current compilation session, the crate is guaranteed to be the same
-                // (otherwise, we would compute a different `DefPathHash`).
-                let raw_def_id = self.get_raw_def_id(&hash)?;
-                debug!("def_path_hash_to_def_id({:?}): raw_def_id = {:?}", hash, raw_def_id);
-                // If the owning crate no longer exists, the corresponding definition definitely
-                // no longer exists.
-                let krate = self.try_remap_cnum(tcx, hash.stable_crate_id())?;
-                debug!("def_path_hash_to_def_id({:?}): krate = {:?}", hash, krate);
-                // If our `DefPathHash` corresponded to a definition in the local crate,
-                // we should have either found it in `local_def_path_hash_to_def_id`, or
-                // never attempted to load it in the first place. Any query result or `DepNode`
-                // that references a local `DefId` should depend on some HIR-related `DepNode`.
-                // If a local definition is removed/modified such that its old `DefPathHash`
-                // no longer has a corresponding definition, that HIR-related `DepNode` should
-                // end up red. This should prevent us from ever calling
-                // `tcx.def_path_hash_to_def_id`, since we'll end up recomputing any
-                // queries involved.
-                debug_assert_ne!(krate, LOCAL_CRATE);
-                // Try to find a definition in the current session, using the previous `DefIndex`
-                // as an initial guess.
-                let opt_def_id =
-                    tcx.cstore_untracked().def_path_hash_to_def_id(krate, raw_def_id.index, hash);
-                debug!("def_path_to_def_id({:?}): opt_def_id = {:?}", hash, opt_def_id);
-                e.insert(opt_def_id);
-                opt_def_id
-            }
-        }
-    }
+    fn def_path_hash_to_def_id(&self, tcx: TyCtxt<'tcx>, hash: DefPathHash) -> DefId {
+        debug!("def_path_hash_to_def_id({:?})", hash);
 
-    fn register_reused_dep_node(&self, tcx: TyCtxt<'sess>, dep_node: &DepNode) {
-        // For reused dep nodes, we only need to store the mapping if the node
-        // is one whose query key we can reconstruct from the hash. We use the
-        // mapping to aid that reconstruction in the next session. While we also
-        // use it to decode `DefId`s we encoded in the cache as `DefPathHashes`,
-        // they're already registered during `DefId` encoding.
-        if dep_node.kind.can_reconstruct_query_key() {
-            let hash = DefPathHash(dep_node.hash.into());
-
-            // We can't simply copy the `RawDefId` from `foreign_def_path_hashes` to
-            // `latest_foreign_def_path_hashes`, since the `RawDefId` might have
-            // changed in the current compilation session (e.g. we've added/removed crates,
-            // or added/removed definitions before/after the target definition).
-            if let Some(def_id) = self.def_path_hash_to_def_id(tcx, hash) {
-                if !def_id.is_local() {
-                    self.store_foreign_def_id_hash(def_id, hash);
-                }
-            }
-        }
-    }
+        let stable_crate_id = hash.stable_crate_id();
 
-    fn store_foreign_def_id_hash(&self, def_id: DefId, hash: DefPathHash) {
-        // We may overwrite an existing entry, but it will have the same value,
-        // so it's fine
-        self.latest_foreign_def_path_hashes
-            .lock()
-            .insert(hash, RawDefId { krate: def_id.krate.as_u32(), index: def_id.index.as_u32() });
+        // If this is a DefPathHash from the local crate, we can look up the
+        // DefId in the tcx's `Definitions`.
+        if stable_crate_id == tcx.sess.local_stable_crate_id() {
+            tcx.definitions_untracked().local_def_path_hash_to_def_id(hash).to_def_id()
+        } else {
+            // If this is a DefPathHash from an upstream crate, let the CrateStore map
+            // it to a DefId.
+            let cnum = tcx.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id);
+            tcx.cstore_untracked().def_path_hash_to_def_id(cnum, hash)
+        }
     }
 }
 
@@ -516,17 +405,6 @@ pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: Que
         debug_assert!(prev.is_none());
     }
 
-    fn get_raw_def_id(&self, hash: &DefPathHash) -> Option<RawDefId> {
-        self.foreign_def_path_hashes.get(hash).copied()
-    }
-
-    fn try_remap_cnum(&self, tcx: TyCtxt<'_>, stable_crate_id: StableCrateId) -> Option<CrateNum> {
-        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
-        debug!("try_remap_cnum({:?}): cnum_map={:?}", stable_crate_id, cnum_map);
-
-        cnum_map.get(&stable_crate_id).copied()
-    }
-
     /// Returns the cached query result if there is something in the cache for
     /// the given `SerializedDepNodeIndex`; otherwise returns `None`.
     pub fn try_load_query_result<'tcx, T>(
@@ -584,14 +462,11 @@ fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T
     where
         T: Decodable<CacheDecoder<'a, 'tcx>>,
     {
-        let cnum_map = self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx));
-
         let serialized_data = self.serialized_data.read();
         let mut decoder = CacheDecoder {
             tcx,
             opaque: opaque::Decoder::new(serialized_data.as_deref().unwrap_or(&[]), pos.to_usize()),
             source_map: self.source_map,
-            cnum_map,
             file_index_to_file: &self.file_index_to_file,
             file_index_to_stable_id: &self.file_index_to_stable_id,
             alloc_decoding_session: self.alloc_decoding_state.new_decoding_session(),
@@ -602,23 +477,6 @@ fn with_decoder<'a, 'tcx, T, F: for<'s> FnOnce(&mut CacheDecoder<'s, 'tcx>) -> T
         };
         f(&mut decoder)
     }
-
-    // This function builds mapping from previous-session-`CrateNum` to
-    // current-session-`CrateNum`. There might be `CrateNum`s from the previous
-    // `Session` that don't occur in the current one. For these, the mapping
-    // maps to None.
-    fn compute_cnum_map(tcx: TyCtxt<'_>) -> UnhashMap<StableCrateId, CrateNum> {
-        tcx.dep_graph.with_ignore(|| {
-            tcx.crates(())
-                .iter()
-                .chain(std::iter::once(&LOCAL_CRATE))
-                .map(|&cnum| {
-                    let hash = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (hash, cnum)
-                })
-                .collect()
-        })
-    }
 }
 
 //- DECODING -------------------------------------------------------------------
@@ -630,7 +488,6 @@ pub struct CacheDecoder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     opaque: opaque::Decoder<'a>,
     source_map: &'a SourceMap,
-    cnum_map: &'a UnhashMap<StableCrateId, CrateNum>,
     file_index_to_file: &'a Lock<FxHashMap<SourceFileIndex, Lrc<SourceFile>>>,
     file_index_to_stable_id: &'a FxHashMap<SourceFileIndex, EncodedSourceFileId>,
     alloc_decoding_session: AllocDecodingSession<'a>,
@@ -643,10 +500,10 @@ pub struct CacheDecoder<'a, 'tcx> {
 impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
     fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
         let CacheDecoder {
+            tcx,
             ref file_index_to_file,
             ref file_index_to_stable_id,
             ref source_map,
-            ref cnum_map,
             ..
         } = *self;
 
@@ -654,7 +511,7 @@ fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
             .borrow_mut()
             .entry(index)
             .or_insert_with(|| {
-                let stable_id = file_index_to_stable_id[&index].translate(cnum_map);
+                let stable_id = file_index_to_stable_id[&index].translate(tcx);
                 source_map
                     .source_file_by_stable_id(stable_id)
                     .expect("failed to lookup `SourceFile` in new context")
@@ -796,7 +653,7 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
             return Ok(expn_id);
         }
 
-        let krate = decoder.cnum_map[&hash.stable_crate_id()];
+        let krate = decoder.tcx.stable_crate_id_to_crate_num(hash.stable_crate_id());
 
         let expn_id = if krate == LOCAL_CRATE {
             // We look up the position of the associated `ExpnData` and decode it.
@@ -829,11 +686,26 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let ctxt = SyntaxContext::decode(decoder)?;
+        let parent = Option::<LocalDefId>::decode(decoder)?;
         let tag: u8 = Decodable::decode(decoder)?;
 
         if tag == TAG_PARTIAL_SPAN {
-            let ctxt = SyntaxContext::decode(decoder)?;
-            return Ok(DUMMY_SP.with_ctxt(ctxt));
+            return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent));
+        } else if tag == TAG_RELATIVE_SPAN {
+            let dlo = u32::decode(decoder)?;
+            let dto = u32::decode(decoder)?;
+
+            let enclosing =
+                decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data_untracked();
+            let span = Span::new(
+                enclosing.lo + BytePos::from_u32(dlo),
+                enclosing.lo + BytePos::from_u32(dto),
+                ctxt,
+                parent,
+            );
+
+            return Ok(span);
         } else {
             debug_assert_eq!(tag, TAG_FULL_SPAN);
         }
@@ -842,20 +714,19 @@ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let line_lo = usize::decode(decoder)?;
         let col_lo = BytePos::decode(decoder)?;
         let len = BytePos::decode(decoder)?;
-        let ctxt = SyntaxContext::decode(decoder)?;
 
         let file_lo = decoder.file_index_to_file(file_lo_index);
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
-        Ok(Span::new(lo, hi, ctxt))
+        Ok(Span::new(lo, hi, ctxt, parent))
     }
 }
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let stable_id = StableCrateId::decode(d)?;
-        let cnum = d.cnum_map[&stable_id];
+        let cnum = d.tcx.stable_crate_id_to_crate_num(stable_id);
         Ok(cnum)
     }
 }
@@ -883,12 +754,7 @@ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         // If we get to this point, then all of the query inputs were green,
         // which means that the definition with this hash is guaranteed to
         // still exist in the current compilation session.
-        Ok(d.tcx()
-            .on_disk_cache
-            .as_ref()
-            .unwrap()
-            .def_path_hash_to_def_id(d.tcx(), def_path_hash)
-            .unwrap())
+        Ok(d.tcx().on_disk_cache.as_ref().unwrap().def_path_hash_to_def_id(d.tcx(), def_path_hash))
     }
 }
 
@@ -906,7 +772,7 @@ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         RefDecodable::decode(d)
     }
@@ -953,7 +819,6 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
     source_map: CachingSourceMapView<'tcx>,
     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
     hygiene_context: &'a HygieneEncodeContext,
-    latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 }
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
@@ -1008,10 +873,22 @@ impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
     E: 'a + OpaqueEncoder,
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let span_data = self.data();
-        if self.is_dummy() {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+        let span_data = self.data_untracked();
+        span_data.ctxt.encode(s)?;
+        span_data.parent.encode(s)?;
+
+        if span_data.is_dummy() {
+            return TAG_PARTIAL_SPAN.encode(s);
+        }
+
+        if let Some(parent) = span_data.parent {
+            let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked();
+            if enclosing.contains(span_data) {
+                TAG_RELATIVE_SPAN.encode(s)?;
+                (span_data.lo - enclosing.lo).to_u32().encode(s)?;
+                (span_data.hi - enclosing.lo).to_u32().encode(s)?;
+                return Ok(());
+            }
         }
 
         let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
@@ -1021,8 +898,7 @@ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         };
 
         if partial_span {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+            return TAG_PARTIAL_SPAN.encode(s);
         }
 
         let (file_lo, line_lo, col_lo) = pos.unwrap();
@@ -1035,8 +911,7 @@ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
         source_file_index.encode(s)?;
         line_lo.encode(s)?;
         col_lo.encode(s)?;
-        len.encode(s)?;
-        span_data.ctxt.encode(s)
+        len.encode(s)
     }
 }
 
@@ -1076,17 +951,7 @@ impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
     E: 'a + OpaqueEncoder,
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let def_path_hash = s.tcx.def_path_hash(*self);
-        // Store additional information when we encode a foreign `DefId`,
-        // so that we can map its `DefPathHash` back to a `DefId` in the next
-        // compilation session.
-        if !self.is_local() {
-            s.latest_foreign_def_path_hashes.insert(
-                def_path_hash,
-                RawDefId { krate: self.krate.as_u32(), index: self.index.as_u32() },
-            );
-        }
-        def_path_hash.encode(s)
+        s.tcx.def_path_hash(*self).encode(s)
     }
 }
 
index 47fb78be6407967736fd3c64ff750d7bc7595951..11c18a497e5e6393d347493b2e82c327eef7cb3a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_query_system"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 59ef6052a60c0b1bcd272b2f1c0512d6dfb4b0ae..46dc0c720ce7f998b133cc619a432171728702e9 100644 (file)
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 pub struct DepNode<K> {
     pub kind: K,
-    // Important - whenever a `DepNode` is constructed, we need to make
-    // sure to register a `DefPathHash -> DefId` mapping if needed.
-    // This is currently done in two places:
-    //
-    // * When a `DepNode::construct` is called, `arg.to_fingerprint()`
-    //   is responsible for calling `OnDiskCache::store_foreign_def_id_hash`
-    //   if needed
-    // * When we serialize the on-disk cache, `OnDiskCache::serialize` is
-    //   responsible for calling `DepGraph::register_reused_dep_nodes`.
-    //
-    // FIXME: Enforce this by preventing manual construction of `DefNode`
-    // (e.g. add a `_priv: ()` field)
     pub hash: PackedFingerprint,
 }
 
index 9c3dad8bd63499caa9204a38ea434506dcb19feb..23a437718427222a7c9440afa148757030e1633e 100644 (file)
@@ -11,6 +11,7 @@
 use parking_lot::Mutex;
 use smallvec::{smallvec, SmallVec};
 use std::collections::hash_map::Entry;
+use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::sync::atomic::Ordering::Relaxed;
@@ -208,89 +209,99 @@ pub fn with_ignore<OP, R>(&self, op: OP) -> R
     ///   `arg` parameter.
     ///
     /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
-    pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
+    pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
         &self,
         key: DepNode<K>,
         cx: Ctxt,
         arg: A,
         task: fn(Ctxt, A) -> R,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+        hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
     ) -> (R, DepNodeIndex) {
-        self.with_task_impl(
-            key,
-            cx,
-            arg,
-            task,
-            |_key| {
-                Some(TaskDeps {
-                    #[cfg(debug_assertions)]
-                    node: Some(_key),
-                    reads: SmallVec::new(),
-                    read_set: Default::default(),
-                    phantom_data: PhantomData,
-                })
-            },
-            hash_result,
-        )
+        if self.is_fully_enabled() {
+            self.with_task_impl(key, cx, arg, task, hash_result)
+        } else {
+            // Incremental compilation is turned off. We just execute the task
+            // without tracking. We still provide a dep-node index that uniquely
+            // identifies the task so that we have a cheap way of referring to
+            // the query for self-profiling.
+            (task(cx, arg), self.next_virtual_depnode_index())
+        }
     }
 
-    fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A, R>(
+    fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
         &self,
         key: DepNode<K>,
         cx: Ctxt,
         arg: A,
         task: fn(Ctxt, A) -> R,
-        create_task: fn(DepNode<K>) -> Option<TaskDeps<K>>,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+        hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
     ) -> (R, DepNodeIndex) {
-        if let Some(ref data) = self.data {
-            let dcx = cx.dep_context();
-            let task_deps = create_task(key).map(Lock::new);
-            let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
-            let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
-
-            let mut hcx = dcx.create_stable_hashing_context();
-            let hashing_timer = dcx.profiler().incr_result_hashing();
-            let current_fingerprint = hash_result(&mut hcx, &result);
-
-            let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
-
-            // Get timer for profiling `DepNode` interning
-            let node_intern_timer = self
-                .node_intern_event_id
-                .map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
-            // Intern the new `DepNode`.
-            let (dep_node_index, prev_and_color) = data.current.intern_node(
-                dcx.profiler(),
-                &data.previous,
-                key,
-                edges,
-                current_fingerprint,
-                print_status,
-            );
-            drop(node_intern_timer);
+        // This function is only called when the graph is enabled.
+        let data = self.data.as_ref().unwrap();
 
-            hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
+        // If the following assertion triggers, it can have two reasons:
+        // 1. Something is wrong with DepNode creation, either here or
+        //    in `DepGraph::try_mark_green()`.
+        // 2. Two distinct query keys get mapped to the same `DepNode`
+        //    (see for example #48923).
+        assert!(
+            !self.dep_node_exists(&key),
+            "forcing query with already existing `DepNode`\n\
+                 - query-key: {:?}\n\
+                 - dep-node: {:?}",
+            arg,
+            key
+        );
 
-            if let Some((prev_index, color)) = prev_and_color {
-                debug_assert!(
-                    data.colors.get(prev_index).is_none(),
-                    "DepGraph::with_task() - Duplicate DepNodeColor \
-                            insertion for {:?}",
-                    key
-                );
+        let task_deps = if key.kind.is_eval_always() {
+            None
+        } else {
+            Some(Lock::new(TaskDeps {
+                #[cfg(debug_assertions)]
+                node: Some(key),
+                reads: SmallVec::new(),
+                read_set: Default::default(),
+                phantom_data: PhantomData,
+            }))
+        };
+        let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
+        let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
+
+        let dcx = cx.dep_context();
+        let mut hcx = dcx.create_stable_hashing_context();
+        let hashing_timer = dcx.profiler().incr_result_hashing();
+        let current_fingerprint = hash_result(&mut hcx, &result);
+
+        let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
+
+        // Get timer for profiling `DepNode` interning
+        let node_intern_timer =
+            self.node_intern_event_id.map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
+        // Intern the new `DepNode`.
+        let (dep_node_index, prev_and_color) = data.current.intern_node(
+            dcx.profiler(),
+            &data.previous,
+            key,
+            edges,
+            current_fingerprint,
+            print_status,
+        );
+        drop(node_intern_timer);
 
-                data.colors.insert(prev_index, color);
-            }
+        hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-            (result, dep_node_index)
-        } else {
-            // Incremental compilation is turned off. We just execute the task
-            // without tracking. We still provide a dep-node index that uniquely
-            // identifies the task so that we have a cheap way of referring to
-            // the query for self-profiling.
-            (task(cx, arg), self.next_virtual_depnode_index())
+        if let Some((prev_index, color)) = prev_and_color {
+            debug_assert!(
+                data.colors.get(prev_index).is_none(),
+                "DepGraph::with_task() - Duplicate DepNodeColor \
+                            insertion for {:?}",
+                key
+            );
+
+            data.colors.insert(prev_index, color);
         }
+
+        (result, dep_node_index)
     }
 
     /// Executes something within an "anonymous" task, that is, a task the
@@ -357,19 +368,6 @@ pub fn with_anon_task<Ctxt: DepContext<DepKind = K>, OP, R>(
         }
     }
 
-    /// Executes something within an "eval-always" task which is a task
-    /// that runs whenever anything changes.
-    pub fn with_eval_always_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
-        &self,
-        key: DepNode<K>,
-        cx: Ctxt,
-        arg: A,
-        task: fn(Ctxt, A) -> R,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
-    ) -> (R, DepNodeIndex) {
-        self.with_task_impl(key, cx, arg, task, |_| None, hash_result)
-    }
-
     #[inline]
     pub fn read_index(&self, dep_node_index: DepNodeIndex) {
         if let Some(ref data) = self.data {
@@ -484,22 +482,11 @@ fn node_color(&self, dep_node: &DepNode<K>) -> Option<DepNodeColor> {
         None
     }
 
-    /// Try to read a node index for the node dep_node.
+    /// Try to mark a node index for the node dep_node.
+    ///
     /// A node will have an index, when it's already been marked green, or when we can mark it
     /// green. This function will mark the current task as a reader of the specified node, when
     /// a node index can be found for that node.
-    pub fn try_mark_green_and_read<Ctxt: QueryContext<DepKind = K>>(
-        &self,
-        tcx: Ctxt,
-        dep_node: &DepNode<K>,
-    ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
-        self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
-            debug_assert!(self.is_green(&dep_node));
-            self.read_index(dep_node_index);
-            (prev_index, dep_node_index)
-        })
-    }
-
     pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>(
         &self,
         tcx: Ctxt,
@@ -773,20 +760,6 @@ pub fn exec_cache_promotions<Ctxt: QueryContext<DepKind = K>>(&self, qcx: Ctxt)
         }
     }
 
-    // Register reused dep nodes (i.e. nodes we've marked red or green) with the context.
-    pub fn register_reused_dep_nodes<Ctxt: DepContext<DepKind = K>>(&self, tcx: Ctxt) {
-        let data = self.data.as_ref().unwrap();
-        for prev_index in data.colors.values.indices() {
-            match data.colors.get(prev_index) {
-                Some(DepNodeColor::Red) | Some(DepNodeColor::Green(_)) => {
-                    let dep_node = data.previous.index_to_node(prev_index);
-                    tcx.register_reused_dep_node(&dep_node);
-                }
-                None => {}
-            }
-        }
-    }
-
     pub fn print_incremental_info(&self) {
         if let Some(data) = &self.data {
             data.current.encoder.borrow().print_incremental_info(
index 15e2633c4f12e79b46da54dd784f04a4a1807f0a..b5be1192ce73fe14833fae7e660ba708fadcc87c 100644 (file)
@@ -27,8 +27,6 @@ pub trait DepContext: Copy {
     /// Access the DepGraph.
     fn dep_graph(&self) -> &DepGraph<Self::DepKind>;
 
-    fn register_reused_dep_node(&self, dep_node: &DepNode<Self::DepKind>);
-
     /// Access the profiler.
     fn profiler(&self) -> &SelfProfilerRef;
 
index 73c00fc49ba39c7794becf632ae0a8d1a9daa973..f5f67fcd0a08c322d3daca93e7ac299ef55a8ed4 100644 (file)
@@ -99,7 +99,7 @@ pub fn node_count(&self) -> usize {
 impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<'a>>
     for SerializedDepGraph<K>
 {
-    #[instrument(skip(d))]
+    #[instrument(level = "debug", skip(d))]
     fn decode(d: &mut opaque::Decoder<'a>) -> Result<SerializedDepGraph<K>, String> {
         let start_position = d.position();
 
@@ -187,7 +187,7 @@ fn new(encoder: FileEncoder, record_stats: bool) -> Self {
         }
     }
 
-    #[instrument(skip(self, record_graph))]
+    #[instrument(level = "debug", skip(self, record_graph))]
     fn encode_node(
         &mut self,
         node: &NodeInfo<K>,
index c3fdf4fc228511b0ebc767267f052461f681196a..98b2a450b19df73ff34e53d5e0078d580ea19b04 100644 (file)
@@ -143,6 +143,8 @@ impl<D> QueryJobId<D>
 where
     D: Copy + Clone + Eq + Hash,
 {
+    #[cold]
+    #[inline(never)]
     pub(super) fn find_cycle_in_stack(
         &self,
         query_map: QueryMap<D>,
index 3f22de6fba4077987d673cb21dfe8a4fea89b830..3534c3242959c1c4f944002e373f11910d6214ad 100644 (file)
@@ -2,8 +2,7 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeParams};
-use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
 use crate::query::caches::QueryCache;
 use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt};
 use crate::query::job::{
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded};
 use rustc_data_structures::sync::{Lock, LockGuard};
 use rustc_data_structures::thin_vec::ThinVec;
-#[cfg(not(parallel_compiler))]
-use rustc_errors::DiagnosticBuilder;
-use rustc_errors::{Diagnostic, FatalError};
+use rustc_errors::{DiagnosticBuilder, FatalError};
 use rustc_span::{Span, DUMMY_SP};
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
@@ -148,24 +147,21 @@ fn default() -> QueryState<D, K> {
 
 /// A type representing the responsibility to execute the job in the `job` field.
 /// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, D, C>
+struct JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
-    state: &'tcx QueryState<D, C::Key>,
-    cache: &'tcx QueryCacheStore<C>,
-    key: C::Key,
+    state: &'tcx QueryState<D, K>,
+    key: K,
     id: QueryJobId<D>,
 }
 
 #[cold]
 #[inline(never)]
-#[cfg(not(parallel_compiler))]
 fn mk_cycle<CTX, V, R>(
     tcx: CTX,
-    root: QueryJobId<CTX::DepKind>,
-    span: Span,
+    error: CycleError,
     handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
     cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
 ) -> R
@@ -174,20 +170,15 @@ fn mk_cycle<CTX, V, R>(
     V: std::fmt::Debug,
     R: Clone,
 {
-    let error: CycleError = root.find_cycle_in_stack(
-        tcx.try_collect_active_jobs().unwrap(),
-        &tcx.current_query_job(),
-        span,
-    );
     let error = report_cycle(tcx.dep_context().sess(), error);
     let value = handle_cycle_error(tcx, error);
     cache.store_nocache(value)
 }
 
-impl<'tcx, D, C> JobOwner<'tcx, D, C>
+impl<'tcx, D, K> JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     /// Either gets a `JobOwner` corresponding the query, allowing us to
     /// start executing the query, or returns with the result of the query.
@@ -199,14 +190,13 @@ impl<'tcx, D, C> JobOwner<'tcx, D, C>
     /// for some compile-time benchmarks.
     #[inline(always)]
     fn try_start<'b, CTX>(
-        tcx: CTX,
-        state: &'b QueryState<CTX::DepKind, C::Key>,
-        cache: &'b QueryCacheStore<C>,
+        tcx: &'b CTX,
+        state: &'b QueryState<CTX::DepKind, K>,
         span: Span,
-        key: C::Key,
+        key: K,
         lookup: QueryLookup,
-        query: &QueryVtable<CTX, C::Key, C::Value>,
-    ) -> TryGetJob<'b, CTX::DepKind, C>
+        dep_kind: CTX::DepKind,
+    ) -> TryGetJob<'b, CTX::DepKind, K>
     where
         CTX: QueryContext,
     {
@@ -227,26 +217,24 @@ fn try_start<'b, CTX>(
                 let key = entry.key().clone();
                 entry.insert(QueryResult::Started(job));
 
-                let global_id = QueryJobId::new(id, shard, query.dep_kind);
-                let owner = JobOwner { state, cache, id: global_id, key };
+                let global_id = QueryJobId::new(id, shard, dep_kind);
+                let owner = JobOwner { state, id: global_id, key };
                 return TryGetJob::NotYetStarted(owner);
             }
             Entry::Occupied(mut entry) => {
                 match entry.get_mut() {
                     #[cfg(not(parallel_compiler))]
                     QueryResult::Started(job) => {
-                        let id = QueryJobId::new(job.id, shard, query.dep_kind);
+                        let id = QueryJobId::new(job.id, shard, dep_kind);
 
                         drop(state_lock);
 
                         // If we are single-threaded we know that we have cycle error,
                         // so we just return the error.
-                        return TryGetJob::Cycle(mk_cycle(
-                            tcx,
-                            id,
+                        return TryGetJob::Cycle(id.find_cycle_in_stack(
+                            tcx.try_collect_active_jobs().unwrap(),
+                            &tcx.current_query_job(),
                             span,
-                            query.handle_cycle_error,
-                            &cache.cache,
                         ));
                     }
                     #[cfg(parallel_compiler)]
@@ -258,7 +246,6 @@ fn try_start<'b, CTX>(
 
                         // Get the latch out
                         let latch = job.latch();
-                        let key = entry.key().clone();
 
                         drop(state_lock);
 
@@ -266,30 +253,10 @@ fn try_start<'b, CTX>(
                         // thread.
                         let result = latch.wait_on(tcx.current_query_job(), span);
 
-                        if let Err(cycle) = result {
-                            let cycle = report_cycle(tcx.dep_context().sess(), cycle);
-                            let value = (query.handle_cycle_error)(tcx, cycle);
-                            let value = cache.cache.store_nocache(value);
-                            return TryGetJob::Cycle(value);
+                        match result {
+                            Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer),
+                            Err(cycle) => TryGetJob::Cycle(cycle),
                         }
-
-                        let cached = cache
-                            .cache
-                            .lookup(cache, &key, |value, index| {
-                                if unlikely!(tcx.dep_context().profiler().enabled()) {
-                                    tcx.dep_context().profiler().query_cache_hit(index.into());
-                                }
-                                #[cfg(debug_assertions)]
-                                {
-                                    cache.cache_hits.fetch_add(1, Ordering::Relaxed);
-                                }
-                                (value.clone(), index)
-                            })
-                            .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
-
-                        query_blocked_prof_timer.finish_with_query_invocation_id(cached.1.into());
-
-                        return TryGetJob::JobCompleted(cached);
                     }
                     QueryResult::Poisoned => FatalError.raise(),
                 }
@@ -299,11 +266,18 @@ fn try_start<'b, CTX>(
 
     /// Completes the query by updating the query cache with the `result`,
     /// signals the waiter and forgets the JobOwner, so it won't poison the query
-    fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
+    fn complete<C>(
+        self,
+        cache: &QueryCacheStore<C>,
+        result: C::Value,
+        dep_node_index: DepNodeIndex,
+    ) -> C::Stored
+    where
+        C: QueryCache<Key = K>,
+    {
         // We can move out of `self` here because we `mem::forget` it below
         let key = unsafe { ptr::read(&self.key) };
         let state = self.state;
-        let cache = self.cache;
 
         // Forget ourself so our destructor won't poison the query
         mem::forget(self);
@@ -330,19 +304,10 @@ fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
     }
 }
 
-fn with_diagnostics<F, R>(f: F) -> (R, ThinVec<Diagnostic>)
-where
-    F: FnOnce(Option<&Lock<ThinVec<Diagnostic>>>) -> R,
-{
-    let diagnostics = Lock::new(ThinVec::new());
-    let result = f(Some(&diagnostics));
-    (result, diagnostics.into_inner())
-}
-
-impl<'tcx, D, C> Drop for JobOwner<'tcx, D, C>
+impl<'tcx, D, K> Drop for JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     #[inline(never)]
     #[cold]
@@ -373,22 +338,22 @@ pub(crate) struct CycleError {
 }
 
 /// The result of `try_start`.
-enum TryGetJob<'tcx, D, C>
+enum TryGetJob<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     /// The query is not yet started. Contains a guard to the cache eventually used to start it.
-    NotYetStarted(JobOwner<'tcx, D, C>),
+    NotYetStarted(JobOwner<'tcx, D, K>),
 
     /// The query was already completed.
     /// Returns the result of the query and its dep-node index
     /// if it succeeded or a cycle error if it failed.
     #[cfg(parallel_compiler)]
-    JobCompleted((C::Stored, DepNodeIndex)),
+    JobCompleted(TimingGuard<'tcx>),
 
     /// Trying to execute the query resulted in a cycle.
-    Cycle(C::Stored),
+    Cycle(CycleError),
 }
 
 /// Checks if the query is already computed and in the cache.
@@ -428,119 +393,146 @@ fn try_execute_query<CTX, C>(
     span: Span,
     key: C::Key,
     lookup: QueryLookup,
+    dep_node: Option<DepNode<CTX::DepKind>>,
     query: &QueryVtable<CTX, C::Key, C::Value>,
     compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
+) -> (C::Stored, Option<DepNodeIndex>)
 where
     C: QueryCache,
-    C::Key: DepNodeParams<CTX::DepContext>,
+    C::Key: Clone + DepNodeParams<CTX::DepContext>,
     CTX: QueryContext,
 {
-    let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
-        tcx,
+    match JobOwner::<'_, CTX::DepKind, C::Key>::try_start(
+        &tcx,
         state,
-        cache,
         span,
         key.clone(),
         lookup,
-        query,
+        query.dep_kind,
     ) {
-        TryGetJob::NotYetStarted(job) => job,
-        TryGetJob::Cycle(result) => return result,
+        TryGetJob::NotYetStarted(job) => {
+            let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id, compute);
+            let result = job.complete(cache, result, dep_node_index);
+            (result, Some(dep_node_index))
+        }
+        TryGetJob::Cycle(error) => {
+            let result = mk_cycle(tcx, error, query.handle_cycle_error, &cache.cache);
+            (result, None)
+        }
         #[cfg(parallel_compiler)]
-        TryGetJob::JobCompleted((v, index)) => {
-            tcx.dep_context().dep_graph().read_index(index);
-            return v;
+        TryGetJob::JobCompleted(query_blocked_prof_timer) => {
+            let (v, index) = cache
+                .cache
+                .lookup(cache, &key, |value, index| (value.clone(), index))
+                .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+
+            if unlikely!(tcx.dep_context().profiler().enabled()) {
+                tcx.dep_context().profiler().query_cache_hit(index.into());
+            }
+            #[cfg(debug_assertions)]
+            {
+                cache.cache_hits.fetch_add(1, Ordering::Relaxed);
+            }
+            query_blocked_prof_timer.finish_with_query_invocation_id(index.into());
+
+            (v, Some(index))
         }
-    };
+    }
+}
 
+fn execute_job<CTX, K, V>(
+    tcx: CTX,
+    key: K,
+    mut dep_node_opt: Option<DepNode<CTX::DepKind>>,
+    query: &QueryVtable<CTX, K, V>,
+    job_id: QueryJobId<CTX::DepKind>,
+    compute: fn(CTX::DepContext, K) -> V,
+) -> (V, DepNodeIndex)
+where
+    K: Clone + DepNodeParams<CTX::DepContext>,
+    V: Debug,
+    CTX: QueryContext,
+{
     let dep_graph = tcx.dep_context().dep_graph();
 
     // Fast path for when incr. comp. is off.
     if !dep_graph.is_fully_enabled() {
         let prof_timer = tcx.dep_context().profiler().query_provider();
-        let result = tcx.start_query(job.id, None, || compute(*tcx.dep_context(), key));
+        let result = tcx.start_query(job_id, None, || compute(*tcx.dep_context(), key));
         let dep_node_index = dep_graph.next_virtual_depnode_index();
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-        return job.complete(result, dep_node_index);
+        return (result, dep_node_index);
     }
 
-    if query.anon {
-        let prof_timer = tcx.dep_context().profiler().query_provider();
+    if !query.anon && !query.eval_always {
+        // `to_dep_node` is expensive for some `DepKind`s.
+        let dep_node =
+            dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key));
 
-        let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-            tcx.start_query(job.id, diagnostics, || {
-                dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
-                    compute(*tcx.dep_context(), key)
-                })
-            })
-        });
+        // The diagnostics for this query will be promoted to the current session during
+        // `try_mark_green()`, so we can ignore them here.
+        if let Some(ret) = tcx.start_query(job_id, None, || {
+            try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query, compute)
+        }) {
+            return ret;
+        }
+    }
 
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+    let prof_timer = tcx.dep_context().profiler().query_provider();
+    let diagnostics = Lock::new(ThinVec::new());
 
-        dep_graph.read_index(dep_node_index);
+    let (result, dep_node_index) = tcx.start_query(job_id, Some(&diagnostics), || {
+        if query.anon {
+            return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
+                compute(*tcx.dep_context(), key)
+            });
+        }
 
-        let side_effects = QuerySideEffects { diagnostics };
+        // `to_dep_node` is expensive for some `DepKind`s.
+        let dep_node = dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key));
 
-        if unlikely!(!side_effects.is_empty()) {
-            tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
-        }
+        dep_graph.with_task(dep_node, *tcx.dep_context(), key, compute, query.hash_result)
+    });
 
-        return job.complete(result, dep_node_index);
-    }
+    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-    let dep_node = query.to_dep_node(*tcx.dep_context(), &key);
+    let diagnostics = diagnostics.into_inner();
+    let side_effects = QuerySideEffects { diagnostics };
 
-    if !query.eval_always {
-        // The diagnostics for this query will be
-        // promoted to the current session during
-        // `try_mark_green()`, so we can ignore them here.
-        let loaded = tcx.start_query(job.id, None, || {
-            let marked = dep_graph.try_mark_green_and_read(tcx, &dep_node);
-            marked.map(|(prev_dep_node_index, dep_node_index)| {
-                (
-                    load_from_disk_and_cache_in_memory(
-                        tcx,
-                        key.clone(),
-                        prev_dep_node_index,
-                        dep_node_index,
-                        &dep_node,
-                        query,
-                        compute,
-                    ),
-                    dep_node_index,
-                )
-            })
-        });
-        if let Some((result, dep_node_index)) = loaded {
-            return job.complete(result, dep_node_index);
+    if unlikely!(!side_effects.is_empty()) {
+        if query.anon {
+            tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
+        } else {
+            tcx.store_side_effects(dep_node_index, side_effects);
         }
     }
 
-    let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute);
-    dep_graph.read_index(dep_node_index);
-    result
+    (result, dep_node_index)
 }
 
-fn load_from_disk_and_cache_in_memory<CTX, K, V: Debug>(
+fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
     tcx: CTX,
-    key: K,
-    prev_dep_node_index: SerializedDepNodeIndex,
-    dep_node_index: DepNodeIndex,
+    key: &K,
     dep_node: &DepNode<CTX::DepKind>,
     query: &QueryVtable<CTX, K, V>,
     compute: fn(CTX::DepContext, K) -> V,
-) -> V
+) -> Option<(V, DepNodeIndex)>
 where
+    K: Clone,
     CTX: QueryContext,
+    V: Debug,
 {
     // Note this function can be called concurrently from the same query
     // We must ensure that this is handled correctly.
 
-    debug_assert!(tcx.dep_context().dep_graph().is_green(dep_node));
+    let dep_graph = tcx.dep_context().dep_graph();
+    let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?;
+
+    debug_assert!(dep_graph.is_green(dep_node));
 
     // First we try to load the result from the on-disk cache.
-    let result = if query.cache_on_disk(tcx, &key, None) {
+    // Some things are never cached on disk.
+    if query.cache_on_disk(tcx, key, None) {
         let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
         let result = query.try_load_from_disk(tcx, prev_dep_node_index);
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -552,43 +544,39 @@ fn load_from_disk_and_cache_in_memory<CTX, K, V: Debug>(
             "missing on-disk cache entry for {:?}",
             dep_node
         );
-        result
-    } else {
-        // Some things are never cached on disk.
-        None
-    };
 
-    if let Some(result) = result {
-        // If `-Zincremental-verify-ich` is specified, re-hash results from
-        // the cache and make sure that they have the expected fingerprint.
-        if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
-            incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+        if let Some(result) = result {
+            // If `-Zincremental-verify-ich` is specified, re-hash results from
+            // the cache and make sure that they have the expected fingerprint.
+            if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+                incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+            }
+
+            return Some((result, dep_node_index));
         }
+    }
 
-        result
-    } else {
-        // We could not load a result from the on-disk cache, so
-        // recompute.
-        let prof_timer = tcx.dep_context().profiler().query_provider();
+    // We could not load a result from the on-disk cache, so
+    // recompute.
+    let prof_timer = tcx.dep_context().profiler().query_provider();
 
-        // The dep-graph for this computation is already in-place.
-        let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key));
+    // The dep-graph for this computation is already in-place.
+    let result = dep_graph.with_ignore(|| compute(*tcx.dep_context(), key.clone()));
 
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-        // Verify that re-running the query produced a result with the expected hash
-        // This catches bugs in query implementations, turning them into ICEs.
-        // For example, a query might sort its result by `DefId` - since `DefId`s are
-        // not stable across compilation sessions, the result could get up getting sorted
-        // in a different order when the query is re-run, even though all of the inputs
-        // (e.g. `DefPathHash` values) were green.
-        //
-        // See issue #82920 for an example of a miscompilation that would get turned into
-        // an ICE by this check
-        incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-        result
-    }
+    // Verify that re-running the query produced a result with the expected hash
+    // This catches bugs in query implementations, turning them into ICEs.
+    // For example, a query might sort its result by `DefId` - since `DefId`s are
+    // not stable across compilation sessions, the result could get up getting sorted
+    // in a different order when the query is re-run, even though all of the inputs
+    // (e.g. `DefPathHash` values) were green.
+    //
+    // See issue #82920 for an example of a miscompilation that would get turned into
+    // an ICE by this check
+    incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+
+    Some((result, dep_node_index))
 }
 
 fn incremental_verify_ich<CTX, K, V: Debug>(
@@ -648,88 +636,6 @@ fn incremental_verify_ich<CTX, K, V: Debug>(
     }
 }
 
-fn force_query_with_job<C, CTX>(
-    tcx: CTX,
-    key: C::Key,
-    job: JobOwner<'_, CTX::DepKind, C>,
-    dep_node: DepNode<CTX::DepKind>,
-    query: &QueryVtable<CTX, C::Key, C::Value>,
-    compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> (C::Stored, DepNodeIndex)
-where
-    C: QueryCache,
-    CTX: QueryContext,
-{
-    // If the following assertion triggers, it can have two reasons:
-    // 1. Something is wrong with DepNode creation, either here or
-    //    in `DepGraph::try_mark_green()`.
-    // 2. Two distinct query keys get mapped to the same `DepNode`
-    //    (see for example #48923).
-    assert!(
-        !tcx.dep_context().dep_graph().dep_node_exists(&dep_node),
-        "forcing query with already existing `DepNode`\n\
-                 - query-key: {:?}\n\
-                 - dep-node: {:?}",
-        key,
-        dep_node
-    );
-
-    let prof_timer = tcx.dep_context().profiler().query_provider();
-
-    let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-        tcx.start_query(job.id, diagnostics, || {
-            if query.eval_always {
-                tcx.dep_context().dep_graph().with_eval_always_task(
-                    dep_node,
-                    *tcx.dep_context(),
-                    key,
-                    compute,
-                    query.hash_result,
-                )
-            } else {
-                tcx.dep_context().dep_graph().with_task(
-                    dep_node,
-                    *tcx.dep_context(),
-                    key,
-                    compute,
-                    query.hash_result,
-                )
-            }
-        })
-    });
-
-    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-    let side_effects = QuerySideEffects { diagnostics };
-
-    if unlikely!(!side_effects.is_empty()) && dep_node.kind != DepKind::NULL {
-        tcx.store_side_effects(dep_node_index, side_effects);
-    }
-
-    let result = job.complete(result, dep_node_index);
-
-    (result, dep_node_index)
-}
-
-#[inline(never)]
-fn get_query_impl<CTX, C>(
-    tcx: CTX,
-    state: &QueryState<CTX::DepKind, C::Key>,
-    cache: &QueryCacheStore<C>,
-    span: Span,
-    key: C::Key,
-    lookup: QueryLookup,
-    query: &QueryVtable<CTX, C::Key, C::Value>,
-    compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
-where
-    CTX: QueryContext,
-    C: QueryCache,
-    C::Key: DepNodeParams<CTX::DepContext>,
-{
-    try_execute_query(tcx, state, cache, span, key, lookup, query, compute)
-}
-
 /// Ensure that either this query has all green inputs or been executed.
 /// Executing `query::ensure(D)` is considered a read of the dep-node `D`.
 /// Returns true if the query should still run.
@@ -739,13 +645,17 @@ fn get_query_impl<CTX, C>(
 ///
 /// Note: The optimization is only available during incr. comp.
 #[inline(never)]
-fn ensure_must_run<CTX, K, V>(tcx: CTX, key: &K, query: &QueryVtable<CTX, K, V>) -> bool
+fn ensure_must_run<CTX, K, V>(
+    tcx: CTX,
+    key: &K,
+    query: &QueryVtable<CTX, K, V>,
+) -> (bool, Option<DepNode<CTX::DepKind>>)
 where
     K: crate::dep_graph::DepNodeParams<CTX::DepContext>,
     CTX: QueryContext,
 {
     if query.eval_always {
-        return true;
+        return (true, None);
     }
 
     // Ensuring an anonymous query makes no sense
@@ -753,19 +663,21 @@ fn ensure_must_run<CTX, K, V>(tcx: CTX, key: &K, query: &QueryVtable<CTX, K, V>)
 
     let dep_node = query.to_dep_node(*tcx.dep_context(), key);
 
-    match tcx.dep_context().dep_graph().try_mark_green_and_read(tcx, &dep_node) {
+    let dep_graph = tcx.dep_context().dep_graph();
+    match dep_graph.try_mark_green(tcx, &dep_node) {
         None => {
-            // A None return from `try_mark_green_and_read` means that this is either
+            // A None return from `try_mark_green` means that this is either
             // a new dep node or that the dep node has already been marked red.
             // Either way, we can't call `dep_graph.read()` as we don't have the
             // DepNodeIndex. We must invoke the query itself. The performance cost
             // this introduces should be negligible as we'll immediately hit the
             // in-memory cache, or another query down the line will.
-            true
+            (true, Some(dep_node))
         }
         Some((_, dep_node_index)) => {
+            dep_graph.read_index(dep_node_index);
             tcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
-            false
+            (false, None)
         }
     }
 }
@@ -804,23 +716,8 @@ fn force_query_impl<CTX, C>(
         Err(lookup) => lookup,
     };
 
-    let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
-        tcx,
-        state,
-        cache,
-        DUMMY_SP,
-        key.clone(),
-        lookup,
-        query,
-    ) {
-        TryGetJob::NotYetStarted(job) => job,
-        TryGetJob::Cycle(_) => return true,
-        #[cfg(parallel_compiler)]
-        TryGetJob::JobCompleted(_) => return true,
-    };
-
-    force_query_with_job(tcx, key, job, dep_node, query, compute);
-
+    let _ =
+        try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), query, compute);
     true
 }
 
@@ -842,25 +739,33 @@ pub fn get_query<Q, CTX>(
     CTX: QueryContext,
 {
     let query = &Q::VTABLE;
-    if let QueryMode::Ensure = mode {
-        if !ensure_must_run(tcx, &key, query) {
+    let dep_node = if let QueryMode::Ensure = mode {
+        let (must_run, dep_node) = ensure_must_run(tcx, &key, query);
+        if !must_run {
             return None;
         }
-    }
+        dep_node
+    } else {
+        None
+    };
 
     debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
     let compute = Q::compute_fn(tcx, &key);
-    let value = get_query_impl(
+    let (result, dep_node_index) = try_execute_query(
         tcx,
         Q::query_state(tcx),
         Q::query_cache(tcx),
         span,
         key,
         lookup,
+        dep_node,
         query,
         compute,
     );
-    Some(value)
+    if let Some(dep_node_index) = dep_node_index {
+        tcx.dep_context().dep_graph().read_index(dep_node_index)
+    }
+    Some(result)
 }
 
 pub fn force_query<Q, CTX>(tcx: CTX, dep_node: &DepNode<CTX::DepKind>) -> bool
index 1581b0562752e9535a9ba2bf76454c70d68fd2ab..f1d3315d6e66a95d7eace650757eb4cc063a1823 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_resolve"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 test = false
index 2ee483d850e7b4ef156e27b48706685be3805fcc..55f2b04c4f1c1f6f258238e5bb8d14829eb5e41b 100644 (file)
@@ -228,7 +228,6 @@ pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
     crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
         let def_id = module.def_id().expect("unpopulated module without a def-id");
         for child in self.cstore().item_children_untracked(def_id, self.session) {
-            let child = child.map_id(|_| panic!("unexpected id"));
             let parent_scope = ParentScope::module(module, self);
             BuildReducedGraphVisitor { r: self, parent_scope }
                 .build_reduced_graph_for_external_crate_res(child);
@@ -946,9 +945,10 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
+    fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
         let parent = self.parent_scope.module;
         let Export { ident, res, vis, span } = child;
+        let res = res.expect_non_local();
         let expansion = self.parent_scope.expansion;
         // Record primary definitions.
         match res {
index 6f4f1bdaea1b7a97929bea82a63ad24c867f4637..5879cb1daa582f5360bb69a332cbf53d3d426635 100644 (file)
@@ -32,7 +32,13 @@ impl<'a, 'b> DefCollector<'a, 'b> {
     fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
         let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
-        self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span)
+        self.resolver.create_def(
+            parent_def,
+            node_id,
+            data,
+            self.expansion.to_expn_id(),
+            span.with_parent(None),
+        )
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
index dfb6d89a0d12601772f5ad183f2fc10b06fe727b..d4782edbc134645305d35091a0c252aa6b163de8 100644 (file)
@@ -11,7 +11,6 @@
 
 use rustc_ast::unwrap_or;
 use rustc_ast::NodeId;
-use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
@@ -1387,13 +1386,13 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
 
         let mut reexports = Vec::new();
 
-        module.for_each_child(self.r, |this, ident, _, binding| {
+        module.for_each_child(self.r, |_, ident, _, binding| {
             // Filter away ambiguous imports and anything that has def-site hygiene.
             // FIXME: Implement actual cross-crate hygiene.
             let is_good_import =
                 binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion();
             if is_good_import || binding.is_macro_def() {
-                let res = binding.res().map_id(|id| this.local_def_id(id));
+                let res = binding.res().expect_non_local();
                 if res != def::Res::Err {
                     reexports.push(Export { ident, res, span: binding.span, vis: binding.vis });
                 }
index b2c0c7874655e0d6fe9fd6bf7a412ab1b5a4fb3b..19136c6ceeb1f6900e186e62c31cd4fbce3330e6 100644 (file)
@@ -12,7 +12,7 @@
 };
 use rustc_ast_pretty::pprust::path_segment_to_string;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, SuggestionStyle};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
@@ -768,6 +768,7 @@ fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option<Span
                                             args[1].span.lo(),
                                             args.last().unwrap().span.hi(),
                                             call_span.ctxt(),
+                                            None,
                                         ))
                                     } else {
                                         None
@@ -1959,11 +1960,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             introduce_suggestion.push((*span, formatter(&lt_name)));
                         }
                     }
-                    err.multipart_suggestion_with_style(
+                    err.multipart_suggestion_verbose(
                         &msg,
                         introduce_suggestion,
                         Applicability::MaybeIncorrect,
-                        SuggestionStyle::ShowAlways,
                     );
                 }
 
@@ -1975,14 +1975,13 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     })
                     .map(|(formatter, span)| (*span, formatter(name)))
                     .collect();
-                err.multipart_suggestion_with_style(
+                err.multipart_suggestion_verbose(
                     &format!(
                         "consider using the `{}` lifetime",
                         lifetime_names.iter().next().unwrap()
                     ),
                     spans_suggs,
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
             };
         let suggest_new = |err: &mut DiagnosticBuilder<'_>, suggs: Vec<Option<String>>| {
@@ -2073,11 +2072,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             };
                             spans_suggs.push((span, sugg.to_string()));
                         }
-                        err.multipart_suggestion_with_style(
+                        err.multipart_suggestion_verbose(
                             "consider using the `'static` lifetime",
                             spans_suggs,
                             Applicability::MaybeIncorrect,
-                            SuggestionStyle::ShowAlways,
                         );
                         continue;
                     }
@@ -2162,11 +2160,10 @@ fn span_underscore_borrow(&self) -> Span {
                         .unwrap_or((span, sugg));
                     introduce_suggestion.push((span, sugg.to_string()));
                 }
-                err.multipart_suggestion_with_style(
+                err.multipart_suggestion_verbose(
                     &msg,
                     introduce_suggestion,
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
                 if should_break {
                     break;
@@ -2242,11 +2239,10 @@ fn span_underscore_borrow(&self) -> Span {
                 if spans_suggs.len() > 0 {
                     // This happens when we have `Foo<T>` where we point at the space before `T`,
                     // but this can be confusing so we give a suggestion with placeholders.
-                    err.multipart_suggestion_with_style(
+                    err.multipart_suggestion_verbose(
                         "consider using one of the available lifetimes here",
                         spans_suggs,
                         Applicability::HasPlaceholders,
-                        SuggestionStyle::ShowAlways,
                     );
                 }
             }
index 4c1d537d55fa37cd3231337c248630f6f5e48ec3..84e7c68713f231d9b231489943ba24d4fa7b2d3d 100644 (file)
@@ -522,8 +522,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
         _ => {}
     }
     let item = {
-        let hir = tcx.hir();
-        let mut parent_iter = hir.parent_iter(hir_id);
+        let mut parent_iter = tcx.hir().parent_iter(hir_id);
         loop {
             let node = parent_iter.next().map(|n| n.1);
             match node {
@@ -1652,7 +1651,11 @@ fn visit_expr(&mut self, ex: &hir::Expr<'_>) {
     }
 
     fn expression_label(ex: &hir::Expr<'_>) -> Option<Ident> {
-        if let hir::ExprKind::Loop(_, Some(label), ..) = ex.kind { Some(label.ident) } else { None }
+        match ex.kind {
+            hir::ExprKind::Loop(_, Some(label), ..) => Some(label.ident),
+            hir::ExprKind::Block(_, Some(label)) => Some(label.ident),
+            _ => None,
+        }
     }
 
     fn check_if_label_shadows_lifetime(tcx: TyCtxt<'_>, mut scope: ScopeRef<'_>, label: Ident) {
@@ -2024,7 +2027,7 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
         // ensure that we issue lints in a repeatable order
         def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id));
 
-        for def_id in def_ids {
+        'lifetimes: for def_id in def_ids {
             debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id);
 
             let lifetimeuseset = self.lifetime_uses.remove(&def_id);
@@ -2067,6 +2070,27 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
                                 {
                                     continue;
                                 }
+
+                                // opaque types generated when desugaring an async function can have a single
+                                // use lifetime even if it is explicitly denied (Issue #77175)
+                                if let hir::Node::Item(hir::Item {
+                                    kind: hir::ItemKind::OpaqueTy(ref opaque),
+                                    ..
+                                }) = self.tcx.hir().get(parent_hir_id)
+                                {
+                                    if opaque.origin != hir::OpaqueTyOrigin::AsyncFn {
+                                        continue 'lifetimes;
+                                    }
+                                    // We want to do this only if the liftime identifier is already defined
+                                    // in the async function that generated this. Otherwise it could be
+                                    // an opaque type defined by the developer and we still want this
+                                    // lint to fail compilation
+                                    for p in opaque.generics.params {
+                                        if defined_by.contains_key(&p.name) {
+                                            continue 'lifetimes;
+                                        }
+                                    }
+                                }
                             }
                         }
 
index 6d2961db9e3dace832a4e86ef6e3663148d7fbb3..d76ba80e42eab75a95eeddd5a836b802714ab616 100644 (file)
@@ -14,6 +14,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
+#![feature(never_type)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 #![allow(rustdoc::private_intra_doc_links)]
@@ -911,7 +912,7 @@ pub struct Resolver<'a> {
 
     /// `CrateNum` resolutions of `extern crate` items.
     extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-    export_map: ExportMap<LocalDefId>,
+    export_map: ExportMap,
     trait_map: Option<NodeMap<Vec<TraitCandidate>>>,
 
     /// A map from nodes to anonymous modules.
@@ -1012,8 +1013,6 @@ pub struct Resolver<'a> {
 
     next_node_id: NodeId,
 
-    def_id_to_span: IndexVec<LocalDefId, Span>,
-
     node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
     def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
 
@@ -1116,6 +1115,11 @@ fn def_key(&mut self, id: DefId) -> DefKey {
         }
     }
 
+    #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.definitions.def_span(id)
+    }
+
     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]
@@ -1197,9 +1201,7 @@ fn create_def(
             disambiguator
         };
 
-        let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator);
-
-        assert_eq!(self.def_id_to_span.push(span), def_id);
+        let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator, span);
 
         // Some things for which we allocate `LocalDefId`s don't correspond to
         // anything in the AST, so they don't have a `NodeId`. For these cases
@@ -1225,6 +1227,11 @@ fn hash_spans(&self) -> bool {
         true
     }
 
+    #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
     #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
@@ -1269,14 +1276,12 @@ pub fn new(
         let mut module_map = FxHashMap::default();
         module_map.insert(root_local_def_id, graph_root);
 
-        let definitions = Definitions::new(session.local_stable_crate_id());
+        let definitions = Definitions::new(session.local_stable_crate_id(), krate.span);
         let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
         visibilities.insert(root_local_def_id, ty::Visibility::Public);
 
-        let mut def_id_to_span = IndexVec::default();
-        assert_eq!(def_id_to_span.push(rustc_span::DUMMY_SP), root);
         let mut def_id_to_node_id = IndexVec::default();
         assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
         let mut node_id_to_def_id = FxHashMap::default();
@@ -1393,7 +1398,6 @@ pub fn new(
                 .collect(),
             lint_buffer: LintBuffer::default(),
             next_node_id: NodeId::from_u32(1),
-            def_id_to_span,
             node_id_to_def_id,
             def_id_to_node_id,
             placeholder_field_indices: Default::default(),
@@ -1487,7 +1491,7 @@ pub fn clone_outputs(&self) -> ResolverOutputs {
                 .iter()
                 .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
                 .collect(),
-            main_def: self.main_def.clone(),
+            main_def: self.main_def,
             trait_impls: self.trait_impls.clone(),
             proc_macros,
             confused_type_with_std_module: self.confused_type_with_std_module.clone(),
@@ -3360,7 +3364,7 @@ pub fn all_macros(&self) -> &FxHashMap<Symbol, Res> {
     /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
+        def_id.as_local().map(|def_id| self.definitions.def_span(def_id))
     }
 
     /// Checks if an expression refers to a function marked with
index 6dc3aa0888a8be605c2e114ecb6555cdd3db28a4..4dbac47c3cc8e35202613a948b6622e5d52a0779 100644 (file)
@@ -180,6 +180,10 @@ fn next_node_id(&mut self) -> NodeId {
         self.next_node_id()
     }
 
+    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId {
+        self.invocation_parents[&id].0
+    }
+
     fn resolve_dollar_crates(&mut self) {
         hygiene::update_dollar_crate_names(|ctxt| {
             let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
index 535a48bcda182baf93ad87881c9aabf88f00ce0e..15a89d82fa69626b373cc0eb40bfe7ea8fcfe874 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_save_analysis"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 tracing = "0.1"
index 593a7563e36a2640520c2a493b8545ae2d5c0585..49778f82253bfddf9558b8e49f72fdc2caf4ef49 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_serialize"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 indexmap = "1"
index ecc8dae04800a3a44dd7c031e8804e238d0ca61f..e32e4493726dbb7d279c66e1451a10d99ccfc41b 100644 (file)
@@ -366,6 +366,18 @@ fn decode(d: &mut D) -> Result<$ty, D::Error> {
     char emit_char read_char
 }
 
+impl<S: Encoder> Encodable<S> for ! {
+    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
+        unreachable!()
+    }
+}
+
+impl<D: Decoder> Decodable<D> for ! {
+    fn decode(_d: &mut D) -> Result<!, D::Error> {
+        unreachable!()
+    }
+}
+
 impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u32(self.get())
index 5b617a2997cd65b55fcde2f76f94972a09aa1b18..4cff21bee3dc37f4bafbbaa0ea71b87b6c9ff24d 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_session"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 getopts = "0.2"
index fdedb7e6a4afe9b2334822fd8afcf0d576f5e0cf..32aa035e1cdecb458faea87ceba51e2f3938c84a 100644 (file)
@@ -1920,9 +1920,10 @@ fn parse_extern_dep_specs(
 
 fn parse_remap_path_prefix(
     matches: &getopts::Matches,
+    debugging_opts: &DebuggingOptions,
     error_format: ErrorOutputType,
 ) -> Vec<(PathBuf, PathBuf)> {
-    matches
+    let mut mapping: Vec<(PathBuf, PathBuf)> = matches
         .opt_strs("remap-path-prefix")
         .into_iter()
         .map(|remap| match remap.rsplit_once('=') {
@@ -1932,7 +1933,15 @@ fn parse_remap_path_prefix(
             ),
             Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
         })
-        .collect()
+        .collect();
+    match &debugging_opts.remap_cwd_prefix {
+        Some(to) => match std::env::current_dir() {
+            Ok(cwd) => mapping.push((cwd, to.clone())),
+            Err(_) => (),
+        },
+        None => (),
+    };
+    mapping
 }
 
 pub fn build_session_options(matches: &getopts::Matches) -> Options {
@@ -2077,7 +2086,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let crate_name = matches.opt_str("crate-name");
 
-    let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
+    let remap_path_prefix = parse_remap_path_prefix(matches, &debugging_opts, error_format);
 
     let pretty = parse_pretty(&debugging_opts, error_format);
 
index 6fe6a555f1af81ccf8f5c6b87039af4bf3ce5a65..9359a55e55a9c74845c6a539f30abb43b3016056 100644 (file)
@@ -1,3 +1,5 @@
+//! A module for searching for libraries
+
 pub use self::FileMatch::*;
 
 use std::env;
@@ -14,8 +16,6 @@ pub enum FileMatch {
     FileDoesntMatch,
 }
 
-// A module for searching for libraries
-
 #[derive(Clone)]
 pub struct FileSearch<'a> {
     sysroot: &'a Path,
@@ -83,22 +83,10 @@ pub fn new(
         FileSearch { sysroot, triple, search_paths, tlib_path, kind }
     }
 
-    // Returns just the directories within the search paths.
+    /// Returns just the directories within the search paths.
     pub fn search_path_dirs(&self) -> Vec<PathBuf> {
         self.search_paths().map(|sp| sp.dir.to_path_buf()).collect()
     }
-
-    // Returns a list of directories where target-specific tool binaries are located.
-    pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
-        let rustlib_path = rustc_target::target_rustlib_path(self.sysroot, &self.triple);
-        let p = std::array::IntoIter::new([
-            Path::new(&self.sysroot),
-            Path::new(&rustlib_path),
-            Path::new("bin"),
-        ])
-        .collect::<PathBuf>();
-        if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
-    }
 }
 
 pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
@@ -107,8 +95,8 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
         .collect::<PathBuf>()
 }
 
-// This function checks if sysroot is found using env::args().next(), and if it
-// is not found, uses env::current_exe() to imply sysroot.
+/// This function checks if sysroot is found using env::args().next(), and if it
+/// is not found, uses env::current_exe() to imply sysroot.
 pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks.  If the resolved path is relative, make it absolute.
     fn canonicalize(path: PathBuf) -> PathBuf {
index 9a1be40558ccb3ca03796f97f6381065301b455e..8110afe75fa92969fb1364a06f748643d2c656ee 100644 (file)
@@ -349,6 +349,7 @@ mod desc {
     pub const parse_threads: &str = parse_number;
     pub const parse_passes: &str = "a space-separated list of passes, or `all`";
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
+    pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
     pub const parse_sanitizers: &str =
         "comma separated list of sanitizers: `address`, `hwaddress`, `leak`, `memory` or `thread`";
@@ -549,7 +550,7 @@ mod parse {
         }
     }
 
-    crate fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
+    crate fn parse_opt_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
         match v {
             Some("unwind") => *slot = Some(PanicStrategy::Unwind),
             Some("abort") => *slot = Some(PanicStrategy::Abort),
@@ -558,6 +559,15 @@ mod parse {
         true
     }
 
+    crate fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
+        match v {
+            Some("unwind") => *slot = PanicStrategy::Unwind,
+            Some("abort") => *slot = PanicStrategy::Abort,
+            _ => return false,
+        }
+        true
+    }
+
     crate fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
         match v {
             Some(s) => match s.parse::<RelroLevel>() {
@@ -958,7 +968,7 @@ mod parse {
         "optimization level (0-3, s, or z; default: 0)"),
     overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "use overflow checks for integer arithmetic"),
-    panic: Option<PanicStrategy> = (None, parse_panic_strategy, [TRACKED],
+    panic: Option<PanicStrategy> = (None, parse_opt_panic_strategy, [TRACKED],
         "panic strategy to compile crate with"),
     passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
         "a list of extra LLVM passes to run (space separated)"),
@@ -1106,6 +1116,8 @@ mod parse {
     incremental_info: bool = (false, parse_bool, [UNTRACKED],
         "print high-level information about incremental reuse (or the lack thereof) \
         (default: no)"),
+    incremental_relative_spans: bool = (false, parse_bool, [TRACKED],
+        "hash spans relative to their parent item for incr. comp. (default: no)"),
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify incr. comp. hashes of green query instances (default: no)"),
     inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1184,6 +1196,8 @@ mod parse {
         "pass `-install_name @rpath/...` to the macOS linker (default: no)"),
     panic_abort_tests: bool = (false, parse_bool, [TRACKED],
         "support compiling tests with panic=abort (default: no)"),
+    panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
+        "panic strategy for panics in drops"),
     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],
@@ -1236,6 +1250,8 @@ mod parse {
         "whether ELF relocations can be relaxed"),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
         "choose which RELRO level to use"),
+    remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+        "remap paths under the current working directory to this path prefix"),
     simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
         to rust's source base directory. only meant for testing purposes"),
index 83b737a73b1e84239a9d5ea1c33cb56e563aede7..acb6c735e051ebc2cfb90b5310e07c7bc8208533 100644 (file)
@@ -9,17 +9,17 @@ pub struct SearchPath {
     pub files: Vec<SearchPathFile>,
 }
 
-// The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But
-// it is searched repeatedly by `find_library_crate`, and the searches involve
-// checking the prefix and suffix of the filename of each `PathBuf`. This is
-// doable, but very slow, because it involves calls to `file_name` and
-// `extension` that are themselves slow.
-//
-// This type augments the `PathBuf` with an `Option<String>` containing the
-// `PathBuf`'s filename. The prefix and suffix checking is much faster on the
-// `Option<String>` than the `PathBuf`. (It's an `Option` because
-// `Path::file_name` can fail; if that happens then all subsequent checking
-// will also fail, which is fine.)
+/// The obvious implementation of `SearchPath::files` is a `Vec<PathBuf>`. But
+/// it is searched repeatedly by `find_library_crate`, and the searches involve
+/// checking the prefix and suffix of the filename of each `PathBuf`. This is
+/// doable, but very slow, because it involves calls to `file_name` and
+/// `extension` that are themselves slow.
+///
+/// This type augments the `PathBuf` with an `Option<String>` containing the
+/// `PathBuf`'s filename. The prefix and suffix checking is much faster on the
+/// `Option<String>` than the `PathBuf`. (It's an `Option` because
+/// `Path::file_name` can fail; if that happens then all subsequent checking
+/// will also fail, which is fine.)
 #[derive(Clone, Debug)]
 pub struct SearchPathFile {
     pub path: PathBuf,
index 4471e1e0ae8b46b7b3534a1407b2054c3fe3275f..d6f4a3ae4f121f76a8594e7662a224f7d057ce79 100644 (file)
@@ -36,7 +36,7 @@
 use std::io::Write;
 use std::num::NonZeroU32;
 use std::ops::{Div, Mul};
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::str::FromStr;
 use std::sync::Arc;
 use std::time::Duration;
@@ -131,9 +131,8 @@ pub struct Session {
     pub target: Target,
     pub host: Target,
     pub opts: config::Options,
-    pub host_tlib_path: SearchPath,
-    /// `None` if the host and target are the same.
-    pub target_tlib_path: Option<SearchPath>,
+    pub host_tlib_path: Lrc<SearchPath>,
+    pub target_tlib_path: Lrc<SearchPath>,
     pub parse_sess: ParseSess,
     pub sysroot: PathBuf,
     /// The name of the root source file of the crate, in the local file system.
@@ -787,8 +786,7 @@ pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
             &self.sysroot,
             self.opts.target_triple.triple(),
             &self.opts.search_paths,
-            // `target_tlib_path == None` means it's the same as `host_tlib_path`.
-            self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path),
+            &self.target_tlib_path,
             kind,
         )
     }
@@ -802,6 +800,18 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
         )
     }
 
+    /// Returns a list of directories where target-specific tool binaries are located.
+    pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
+        let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple());
+        let p = std::array::IntoIter::new([
+            Path::new(&self.sysroot),
+            Path::new(&rustlib_path),
+            Path::new("bin"),
+        ])
+        .collect::<PathBuf>();
+        if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] }
+    }
+
     pub fn init_incr_comp_session(
         &self,
         session_dir: PathBuf,
@@ -1245,11 +1255,13 @@ pub fn build_session(
 
     let host_triple = config::host_triple();
     let target_triple = sopts.target_triple.triple();
-    let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple);
+    let host_tlib_path = Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple));
     let target_tlib_path = if host_triple == target_triple {
-        None
+        // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary
+        // rescanning of the target lib path and an unnecessary allocation.
+        host_tlib_path.clone()
     } else {
-        Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
+        Lrc::new(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
     };
 
     let file_path_mapping = sopts.file_path_mapping();
index e475e89d87e8ec03fb9d2afb174f5745964e9084..781fb8c1e5d8c8644dfe872cdb22943cb76daae1 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_span"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index 8e21b9ff44a1b267d67a4c6f24cd07e49f1b4787..fdabf404a37fb0f0b1d76331c4d91c6d043becc5 100644 (file)
@@ -215,13 +215,13 @@ pub fn span_data_to_lines_and_cols(
 
         // Span lo and hi may equal line end when last line doesn't
         // end in newline, hence the inclusive upper bounds below.
-        debug_assert!(span_data.lo >= lo.line.start);
-        debug_assert!(span_data.lo <= lo.line.end);
-        debug_assert!(span_data.hi >= hi.line.start);
-        debug_assert!(span_data.hi <= hi.line.end);
-        debug_assert!(lo.file.contains(span_data.lo));
-        debug_assert!(lo.file.contains(span_data.hi));
-        debug_assert_eq!(lo.file_index, hi.file_index);
+        assert!(span_data.lo >= lo.line.start);
+        assert!(span_data.lo <= lo.line.end);
+        assert!(span_data.hi >= hi.line.start);
+        assert!(span_data.hi <= hi.line.end);
+        assert!(lo.file.contains(span_data.lo));
+        assert!(lo.file.contains(span_data.hi));
+        assert_eq!(lo.file_index, hi.file_index);
 
         Some((
             lo.file.clone(),
index c22093c5a428811ac78241029325969330873b41..ef60608a27c8bb6bb03e1fe56e1ea54ab1af908b 100644 (file)
@@ -1357,9 +1357,7 @@ fn for_all_expns_in<E>(
     mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
 ) -> Result<(), E> {
     let all_data: Vec<_> = HygieneData::with(|data| {
-        expns
-            .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone()))
-            .collect()
+        expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
     });
     for (expn, data, hash) in all_data.into_iter() {
         f(expn, &data, hash)?;
index 5f41b1120126eece0e35c0f9df44b26eb74f9390..9c5469f635f71ee8c3f6d136d9b60f19242ea749 100644 (file)
@@ -41,7 +41,7 @@
 pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
 pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
 pub mod def_id;
-use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
+use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
 pub mod lev_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -78,7 +78,7 @@
 // threads within the compilation session, but is not accessible outside the
 // session.
 pub struct SessionGlobals {
-    symbol_interner: Lock<symbol::Interner>,
+    symbol_interner: symbol::Interner,
     span_interner: Lock<span_encoding::SpanInterner>,
     hygiene_data: Lock<hygiene::HygieneData>,
     source_map: Lock<Option<Lrc<SourceMap>>>,
@@ -87,7 +87,7 @@ pub struct SessionGlobals {
 impl SessionGlobals {
     pub fn new(edition: Edition) -> SessionGlobals {
         SessionGlobals {
-            symbol_interner: Lock::new(symbol::Interner::fresh()),
+            symbol_interner: symbol::Interner::fresh(),
             span_interner: Lock::new(span_encoding::SpanInterner::default()),
             hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
             source_map: Lock::new(None),
@@ -434,24 +434,38 @@ pub struct SpanData {
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
     pub ctxt: SyntaxContext,
+    pub parent: Option<LocalDefId>,
 }
 
 impl SpanData {
     #[inline]
     pub fn span(&self) -> Span {
-        Span::new(self.lo, self.hi, self.ctxt)
+        Span::new(self.lo, self.hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_lo(&self, lo: BytePos) -> Span {
-        Span::new(lo, self.hi, self.ctxt)
+        Span::new(lo, self.hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_hi(&self, hi: BytePos) -> Span {
-        Span::new(self.lo, hi, self.ctxt)
+        Span::new(self.lo, hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
-        Span::new(self.lo, self.hi, ctxt)
+        Span::new(self.lo, self.hi, ctxt, self.parent)
+    }
+    #[inline]
+    pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
+        Span::new(self.lo, self.hi, self.ctxt, parent)
+    }
+    /// Returns `true` if this is a dummy span with any hygienic context.
+    #[inline]
+    pub fn is_dummy(self) -> bool {
+        self.lo.0 == 0 && self.hi.0 == 0
+    }
+    /// Returns `true` if `self` fully encloses `other`.
+    pub fn contains(self, other: Self) -> bool {
+        self.lo <= other.lo && other.hi <= self.hi
     }
 }
 
@@ -507,18 +521,25 @@ pub fn with_hi(self, hi: BytePos) -> Span {
     }
     #[inline]
     pub fn ctxt(self) -> SyntaxContext {
-        self.data().ctxt
+        self.data_untracked().ctxt
     }
     #[inline]
     pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
-        self.data().with_ctxt(ctxt)
+        self.data_untracked().with_ctxt(ctxt)
+    }
+    #[inline]
+    pub fn parent(self) -> Option<LocalDefId> {
+        self.data().parent
+    }
+    #[inline]
+    pub fn with_parent(self, ctxt: Option<LocalDefId>) -> Span {
+        self.data().with_parent(ctxt)
     }
 
     /// Returns `true` if this is a dummy span with any hygienic context.
     #[inline]
     pub fn is_dummy(self) -> bool {
-        let span = self.data();
-        span.lo.0 == 0 && span.hi.0 == 0
+        self.data_untracked().is_dummy()
     }
 
     /// Returns `true` if this span comes from a macro or desugaring.
@@ -534,26 +555,26 @@ pub fn in_derive_expansion(self) -> bool {
 
     #[inline]
     pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
-        Span::new(lo, hi, SyntaxContext::root())
+        Span::new(lo, hi, SyntaxContext::root(), None)
     }
 
     /// Returns a new span representing an empty span at the beginning of this span.
     #[inline]
     pub fn shrink_to_lo(self) -> Span {
-        let span = self.data();
+        let span = self.data_untracked();
         span.with_hi(span.lo)
     }
     /// Returns a new span representing an empty span at the end of this span.
     #[inline]
     pub fn shrink_to_hi(self) -> Span {
-        let span = self.data();
+        let span = self.data_untracked();
         span.with_lo(span.hi)
     }
 
     #[inline]
     /// Returns `true` if `hi == lo`.
     pub fn is_empty(&self) -> bool {
-        let span = self.data();
+        let span = self.data_untracked();
         span.hi == span.lo
     }
 
@@ -566,7 +587,7 @@ pub fn substitute_dummy(self, other: Span) -> Span {
     pub fn contains(self, other: Span) -> bool {
         let span = self.data();
         let other = other.data();
-        span.lo <= other.lo && other.hi <= span.hi
+        span.contains(other)
     }
 
     /// Returns `true` if `self` touches `other`.
@@ -602,7 +623,7 @@ pub fn source_callsite(self) -> Span {
 
     /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
     /// if any.
-    pub fn parent(self) -> Option<Span> {
+    pub fn parent_callsite(self) -> Option<Span> {
         let expn_data = self.ctxt().outer_expn_data();
         if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
     }
@@ -610,7 +631,7 @@ pub fn parent(self) -> Option<Span> {
     /// 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()?;
+            self = self.parent_callsite()?;
         }
         Some(self)
     }
@@ -731,6 +752,7 @@ pub fn to(self, end: Span) -> Span {
             cmp::min(span_data.lo, end_data.lo),
             cmp::max(span_data.hi, end_data.hi),
             if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
+            if span_data.parent == end_data.parent { span_data.parent } else { None },
         )
     }
 
@@ -748,6 +770,7 @@ pub fn between(self, end: Span) -> Span {
             span.hi,
             end.lo,
             if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+            if span.parent == end.parent { span.parent } else { None },
         )
     }
 
@@ -765,6 +788,7 @@ pub fn until(self, end: Span) -> Span {
             span.lo,
             end.lo,
             if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+            if span.parent == end.parent { span.parent } else { None },
         )
     }
 
@@ -774,6 +798,7 @@ pub fn from_inner(self, inner: InnerSpan) -> Span {
             span.lo + BytePos::from_usize(inner.start),
             span.lo + BytePos::from_usize(inner.end),
             span.ctxt,
+            span.parent,
         )
     }
 
@@ -812,7 +837,7 @@ pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span {
     pub fn remove_mark(&mut self) -> ExpnId {
         let mut span = self.data();
         let mark = span.ctxt.remove_mark();
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -820,7 +845,7 @@ pub fn remove_mark(&mut self) -> ExpnId {
     pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
         let mark = span.ctxt.adjust(expn_id);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -828,7 +853,7 @@ pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
     pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
         let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -836,7 +861,7 @@ pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<
     pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
         let mut span = self.data();
         let mark = span.ctxt.glob_adjust(expn_id, glob_span);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -848,7 +873,7 @@ pub fn reverse_glob_adjust(
     ) -> Option<Option<ExpnId>> {
         let mut span = self.data();
         let mark = span.ctxt.reverse_glob_adjust(expn_id, glob_span);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -900,7 +925,7 @@ impl<D: Decoder> Decodable<D> for Span {
             let lo = d.read_struct_field("lo", Decodable::decode)?;
             let hi = d.read_struct_field("hi", Decodable::decode)?;
 
-            Ok(Span::new(lo, hi, SyntaxContext::root()))
+            Ok(Span::new(lo, hi, SyntaxContext::root(), None))
         })
     }
 }
@@ -961,7 +986,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl fmt::Debug for SpanData {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt), f)
+        (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt, self.parent), f)
     }
 }
 
@@ -1922,6 +1947,7 @@ pub struct FileLines {
 
 pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
     AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
 
 // _____________________________________________________________________________
 // SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
@@ -1976,6 +2002,7 @@ pub fn new(start: usize, end: usize) -> InnerSpan {
 pub trait HashStableContext {
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
     fn hash_spans(&self) -> bool;
+    fn def_span(&self, def_id: LocalDefId) -> Span;
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
@@ -1999,22 +2026,35 @@ impl<CTX> HashStable<CTX> for Span
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         const TAG_VALID_SPAN: u8 = 0;
         const TAG_INVALID_SPAN: u8 = 1;
+        const TAG_RELATIVE_SPAN: u8 = 2;
 
         if !ctx.hash_spans() {
             return;
         }
 
-        self.ctxt().hash_stable(ctx, hasher);
+        let span = self.data_untracked();
+        span.ctxt.hash_stable(ctx, hasher);
+        span.parent.hash_stable(ctx, hasher);
 
-        if self.is_dummy() {
+        if span.is_dummy() {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
             return;
         }
 
+        if let Some(parent) = span.parent {
+            let def_span = ctx.def_span(parent).data_untracked();
+            if def_span.contains(span) {
+                // This span is enclosed in a definition: only hash the relative position.
+                Hash::hash(&TAG_RELATIVE_SPAN, hasher);
+                (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                return;
+            }
+        }
+
         // If this is not an empty or invalid span, we want to hash the last
         // position that belongs to it, as opposed to hashing the first
         // position past it.
-        let span = self.data();
         let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
         {
             Some(pos) => pos,
index 9b8c8594ee843e88d5a4546a5566cfd624a8ed69..9e403eb3f67f3de9424a003c1ef56f68b4f899a2 100644 (file)
@@ -794,7 +794,7 @@ pub fn next_point(&self, sp: Span) -> Span {
             start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point);
 
         let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point));
-        Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt())
+        Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
     }
 
     /// Finds the width of the character, either before or after the end of provided span,
index cb017709c6c7bfc071268a71779f2c230f34827f..e9120b98aabc6e2e9bae1e71c8ce89418e874b7b 100644 (file)
@@ -4,7 +4,9 @@
 // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
 // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
 
+use crate::def_id::LocalDefId;
 use crate::hygiene::SyntaxContext;
+use crate::SPAN_TRACK;
 use crate::{BytePos, SpanData};
 
 use rustc_data_structures::fx::FxIndexSet;
 ///   the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
 ///   but larger crates might need more than 16 bits.
 ///
+/// In order to reliably use parented spans in incremental compilation,
+/// the dependency to the parent definition's span. This is performed
+/// using the callback `SPAN_TRACK` to access the query engine.
+///
 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
 pub struct Span {
     base_or_index: u32,
@@ -70,25 +76,42 @@ pub struct Span {
 
 impl Span {
     #[inline]
-    pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self {
+    pub fn new(
+        mut lo: BytePos,
+        mut hi: BytePos,
+        ctxt: SyntaxContext,
+        parent: Option<LocalDefId>,
+    ) -> Self {
         if lo > hi {
             std::mem::swap(&mut lo, &mut hi);
         }
 
         let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32());
 
-        if len <= MAX_LEN && ctxt2 <= MAX_CTXT {
+        if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() {
             // Inline format.
             Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 }
         } else {
             // Interned format.
-            let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt }));
+            let index =
+                with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }));
             Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 }
         }
     }
 
     #[inline]
     pub fn data(self) -> SpanData {
+        let data = self.data_untracked();
+        if let Some(parent) = data.parent {
+            (*SPAN_TRACK)(parent);
+        }
+        data
+    }
+
+    /// Internal function to translate between an encoded span and the expanded representation.
+    /// This function must not be used outside the incremental engine.
+    #[inline]
+    pub fn data_untracked(self) -> SpanData {
         if self.len_or_tag != LEN_TAG {
             // Inline format.
             debug_assert!(self.len_or_tag as u32 <= MAX_LEN);
@@ -96,6 +119,7 @@ pub fn data(self) -> SpanData {
                 lo: BytePos(self.base_or_index),
                 hi: BytePos(self.base_or_index + self.len_or_tag as u32),
                 ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32),
+                parent: None,
             }
         } else {
             // Interned format.
index 24023163cc30eb2b2ca072313f21f421f86b5764..322bea3806cfa5eef8695afb484db53b86b6e93c 100644 (file)
@@ -5,6 +5,7 @@
 use rustc_arena::DroplessArena;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_data_structures::sync::Lock;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 
         panic_2021,
         panic_abort,
         panic_bounds_check,
+        panic_display,
         panic_fmt,
         panic_handler,
         panic_impl,
         panic_unwind,
         panicking,
         param_attrs,
-        parent_trait,
         partial_cmp,
         partial_ord,
         passes,
         rustc_synthetic,
         rustc_test_marker,
         rustc_then_this_would_need,
+        rustc_trivial_field_reads,
         rustc_unsafe_specialization_marker,
         rustc_variance,
         rustdoc,
         simd_select_bitmask,
         simd_shl,
         simd_shr,
+        simd_shuffle,
         simd_sub,
         simd_trunc,
         simd_xor,
         unix,
         unlikely,
         unmarked_api,
-        unnamed_fields,
         unpin,
         unreachable,
         unreachable_code,
         wrapping_sub,
         wreg,
         write_bytes,
+        write_str,
         x87_reg,
         xer,
         xmm_reg,
@@ -1622,14 +1625,15 @@ const fn new(n: u32) -> Self {
 
     /// Maps a string to its interned representation.
     pub fn intern(string: &str) -> Self {
-        with_interner(|interner| interner.intern(string))
+        with_session_globals(|session_globals| session_globals.symbol_interner.intern(string))
     }
 
     /// Convert to a `SymbolStr`. This is a slowish operation because it
     /// requires locking the symbol interner.
     pub fn as_str(self) -> SymbolStr {
-        with_interner(|interner| unsafe {
-            SymbolStr { string: std::mem::transmute::<&str, &str>(interner.get(self)) }
+        with_session_globals(|session_globals| {
+            let symbol_str = session_globals.symbol_interner.get(self);
+            unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } }
         })
     }
 
@@ -1638,7 +1642,7 @@ pub fn as_u32(self) -> u32 {
     }
 
     pub fn len(self) -> usize {
-        with_interner(|interner| interner.get(self).len())
+        with_session_globals(|session_globals| session_globals.symbol_interner.get(self).len())
     }
 
     pub fn is_empty(self) -> bool {
@@ -1695,13 +1699,19 @@ fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr {
     }
 }
 
+#[derive(Default)]
+pub(crate) struct Interner(Lock<InternerInner>);
+
 // The `&'static str`s in this type actually point into the arena.
 //
 // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
 // found that to regress performance up to 2% in some cases. This might be
 // revisited after further improvements to `indexmap`.
+//
+// This type is private to prevent accidentally constructing more than one `Interner` on the same
+// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
 #[derive(Default)]
-pub struct Interner {
+struct InternerInner {
     arena: DroplessArena,
     names: FxHashMap<&'static str, Symbol>,
     strings: Vec<&'static str>,
@@ -1709,37 +1719,38 @@ pub struct Interner {
 
 impl Interner {
     fn prefill(init: &[&'static str]) -> Self {
-        Interner {
+        Interner(Lock::new(InternerInner {
             strings: init.into(),
             names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
             ..Default::default()
-        }
+        }))
     }
 
     #[inline]
-    pub fn intern(&mut self, string: &str) -> Symbol {
-        if let Some(&name) = self.names.get(string) {
+    fn intern(&self, string: &str) -> Symbol {
+        let mut inner = self.0.lock();
+        if let Some(&name) = inner.names.get(string) {
             return name;
         }
 
-        let name = Symbol::new(self.strings.len() as u32);
+        let name = Symbol::new(inner.strings.len() as u32);
 
         // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
         // UTF-8.
         let string: &str =
-            unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
+            unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
         // It is safe to extend the arena allocation to `'static` because we only access
         // these while the arena is still alive.
         let string: &'static str = unsafe { &*(string as *const str) };
-        self.strings.push(string);
-        self.names.insert(string, name);
+        inner.strings.push(string);
+        inner.names.insert(string, name);
         name
     }
 
     // Get the symbol as a string. `Symbol::as_str()` should be used in
     // preference to this function.
-    pub fn get(&self, symbol: Symbol) -> &str {
-        self.strings[symbol.0.as_usize()]
+    fn get(&self, symbol: Symbol) -> &str {
+        self.0.lock().strings[symbol.0.as_usize()]
     }
 }
 
@@ -1870,11 +1881,6 @@ pub fn is_raw_guess(self) -> bool {
     }
 }
 
-#[inline]
-fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
-    with_session_globals(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
-}
-
 /// An alternative to [`Symbol`], useful when the chars within the symbol need to
 /// be accessed. It deliberately has limited functionality and should only be
 /// used for temporary values.
index 11dea265b4e66c6adb3769195bf6d234bbf8919f..0958fce5fee304fbd6f918a16efcf40e65e47cef 100644 (file)
@@ -4,7 +4,7 @@
 
 #[test]
 fn interner_tests() {
-    let mut i: Interner = Interner::default();
+    let i = Interner::default();
     // first one is zero:
     assert_eq!(i.intern("dog"), Symbol::new(0));
     // re-use gets the same entry:
index aebf77a1fd85ffc1e276068968eea533c387f3da..d5befa10e23638f7bd9fd7860284c8d1fa6dae36 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_symbol_mangling"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index e47a84dbc117e4851aecf8d7cc93eaa1db30a1bb..925813e6bb42762ff5887618910312df4e15a215 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_target"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 bitflags = "1.2.1"
diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs
new file mode 100644 (file)
index 0000000..58fdc00
--- /dev/null
@@ -0,0 +1,30 @@
+use crate::abi::call::{ArgAbi, FnAbi};
+
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
+    if ret.layout.is_aggregate() {
+        ret.make_indirect();
+    } else {
+        ret.extend_integer_width_to(32);
+    }
+}
+
+fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
+    if arg.layout.is_aggregate() {
+        arg.make_indirect_byval();
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
+    if !fn_abi.ret.is_ignore() {
+        classify_ret(&mut fn_abi.ret);
+    }
+
+    for arg in &mut fn_abi.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg(arg);
+    }
+}
index 28ca93c46921e1cd7f69e770f89e99a7c722b40b..2e00ffc7e14730a916f95b3d3514ad74dc9dfe9d 100644 (file)
@@ -3,7 +3,7 @@
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
-    if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+    if let abi::Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, signed) = scalar.value {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
@@ -23,7 +23,7 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
     C: HasDataLayout,
 {
     match ret.layout.field(cx, i).abi {
-        abi::Abi::Scalar(ref scalar) => match scalar.value {
+        abi::Abi::Scalar(scalar) => match scalar.value {
             abi::F32 => Some(Reg::f32()),
             abi::F64 => Some(Reg::f64()),
             _ => None,
@@ -107,7 +107,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
                 let offset = arg.layout.fields.offset(i);
 
                 // We only care about aligned doubles
-                if let abi::Abi::Scalar(ref scalar) = field.abi {
+                if let abi::Abi::Scalar(scalar) = field.abi {
                     if let abi::F64 = scalar.value {
                         if offset.is_aligned(dl.f64_align.abi) {
                             // Insert enough integers to cover [last_offset, offset)
index 6d3c7318091076fbcbb0b2f7b5fab6c70ef5cfc7..d9eb299e2fd350781725927aade13b5bfad1166c 100644 (file)
@@ -1,6 +1,7 @@
 use crate::abi::{self, Abi, Align, FieldsShape, Size};
 use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::{self, HasTargetSpec};
+use std::fmt;
 
 mod aarch64;
 mod amdgpu;
@@ -8,6 +9,7 @@
 mod avr;
 mod bpf;
 mod hexagon;
+mod m68k;
 mod mips;
 mod mips64;
 mod msp430;
@@ -24,7 +26,7 @@
 mod x86_64;
 mod x86_win64;
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum PassMode {
     /// Ignore the argument.
     ///
@@ -59,7 +61,7 @@ pub enum PassMode {
 mod attr_impl {
     // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
     bitflags::bitflags! {
-        #[derive(Default)]
+        #[derive(Default, HashStable_Generic)]
         pub struct ArgAttribute: u16 {
             const NoAlias   = 1 << 1;
             const NoCapture = 1 << 2;
@@ -76,7 +78,7 @@ pub struct ArgAttribute: u16 {
 /// Sometimes an ABI requires small integers to be extended to a full or partial register. This enum
 /// defines if this extension should be zero-extension or sign-extension when necessary. When it is
 /// not necessary to extend the argument, this enum is ignored.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum ArgExtension {
     None,
     Zext,
@@ -85,7 +87,7 @@ pub enum ArgExtension {
 
 /// A compact representation of LLVM attributes (at least those relevant for this module)
 /// that can be manipulated without interacting with LLVM's Attribute machinery.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct ArgAttributes {
     pub regular: ArgAttribute,
     pub arg_ext: ArgExtension,
@@ -126,14 +128,14 @@ pub fn contains(&self, attr: ArgAttribute) -> bool {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum RegKind {
     Integer,
     Float,
     Vector,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Reg {
     pub kind: RegKind,
     pub size: Size,
@@ -183,7 +185,7 @@ pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
 
 /// An argument passed entirely registers with the
 /// same kind (e.g., HFA / HVA on PPC64 and AArch64).
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Uniform {
     pub unit: Reg,
 
@@ -208,7 +210,7 @@ pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
     }
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct CastTarget {
     pub prefix: [Option<RegKind>; 8],
     pub prefix_chunk_size: Size,
@@ -322,7 +324,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
             Abi::Uninhabited => Err(Heterogeneous),
 
             // The primitive for this algorithm.
-            Abi::Scalar(ref scalar) => {
+            Abi::Scalar(scalar) => {
                 let kind = match scalar.value {
                     abi::Int(..) | abi::Pointer => RegKind::Integer,
                     abi::F32 | abi::F64 => RegKind::Float,
@@ -436,7 +438,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
 
 /// Information about how to pass an argument to,
 /// or return a value from, a function, under some ABI.
-#[derive(Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct ArgAbi<'a, Ty> {
     pub layout: TyAndLayout<'a, Ty>,
 
@@ -450,9 +452,9 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     pub fn new(
         cx: &impl HasDataLayout,
         layout: TyAndLayout<'a, Ty>,
-        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes,
+        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes,
     ) -> Self {
-        let mode = match &layout.abi {
+        let mode = match layout.abi {
             Abi::Uninhabited => PassMode::Ignore,
             Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
             Abi::ScalarPair(a, b) => PassMode::Pair(
@@ -504,7 +506,7 @@ pub fn make_indirect_byval(&mut self) {
 
     pub fn extend_integer_width_to(&mut self, bits: u64) {
         // Only integers have signedness
-        if let Abi::Scalar(ref scalar) = self.layout.abi {
+        if let Abi::Scalar(scalar) = self.layout.abi {
             if let abi::Int(i, signed) = scalar.value {
                 if i.size().bits() < bits {
                     if let PassMode::Direct(ref mut attrs) = self.mode {
@@ -544,7 +546,7 @@ pub fn is_ignore(&self) -> bool {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Conv {
     // General language calling conventions, for which every target
     // should have its own backend (e.g. LLVM) support.
@@ -578,7 +580,7 @@ pub enum Conv {
 ///
 /// I will do my best to describe this structure, but these
 /// comments are reverse-engineered and may be inaccurate. -NDM
-#[derive(Debug)]
+#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct FnAbi<'a, Ty> {
     /// The LLVM types of each argument.
     pub args: Vec<ArgAbi<'a, Ty>>,
@@ -599,8 +601,29 @@ pub struct FnAbi<'a, Ty> {
     pub can_unwind: bool,
 }
 
+/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
+#[derive(Clone, Debug, HashStable_Generic)]
+pub enum AdjustForForeignAbiError {
+    /// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs.
+    Unsupported { arch: String, abi: spec::abi::Abi },
+}
+
+impl fmt::Display for AdjustForForeignAbiError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Unsupported { arch, abi } => {
+                write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi)
+            }
+        }
+    }
+}
+
 impl<'a, Ty> FnAbi<'a, Ty> {
-    pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
+    pub fn adjust_for_foreign_abi<C>(
+        &mut self,
+        cx: &C,
+        abi: spec::abi::Abi,
+    ) -> Result<(), AdjustForForeignAbiError>
     where
         Ty: TyAbiInterface<'a, C> + Copy,
         C: HasDataLayout + HasTargetSpec,
@@ -634,6 +657,7 @@ pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(),
             "amdgpu" => amdgpu::compute_abi_info(cx, self),
             "arm" => arm::compute_abi_info(cx, self),
             "avr" => avr::compute_abi_info(self),
+            "m68k" => m68k::compute_abi_info(self),
             "mips" => mips::compute_abi_info(cx, self),
             "mips64" => mips64::compute_abi_info(cx, self),
             "powerpc" => powerpc::compute_abi_info(self),
@@ -655,7 +679,9 @@ pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(),
             }
             "asmjs" => wasm::compute_c_abi_info(cx, self),
             "bpf" => bpf::compute_abi_info(self),
-            a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
+            arch => {
+                return Err(AdjustForForeignAbiError::Unsupported { arch: arch.to_string(), abi });
+            }
         }
 
         Ok(())
index 8c2ef8c7a017dfe130e2ac1799faee0241fdaff3..bbefc73a076d7dd7ccb0b10efc8b7a6ac5a21e99 100644 (file)
@@ -44,7 +44,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
     Ty: TyAbiInterface<'a, C> + Copy,
 {
     match arg_layout.abi {
-        Abi::Scalar(ref scalar) => match scalar.value {
+        Abi::Scalar(scalar) => match scalar.value {
             abi::Int(..) | abi::Pointer => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
@@ -297,7 +297,7 @@ fn classify_arg<'a, Ty, C>(
 }
 
 fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
-    if let Abi::Scalar(ref scalar) = arg.layout.abi {
+    if let Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, _) = scalar.value {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
index 594108925de8093e4ac90159ab035c714aff2c9b..38aaee64a4d6b6978daa0a02c0933aed38542958 100644 (file)
@@ -18,7 +18,7 @@ fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
     C: HasDataLayout,
 {
     match layout.abi {
-        abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
         abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
index 3fc197b5d7537f494c7e830c776c19526b3324d5..28064d85bf1710ae6a218d43060951af9a763e5b 100644 (file)
@@ -14,7 +14,7 @@ fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
     C: HasDataLayout,
 {
     match layout.abi {
-        abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
         abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
index 08f0aaba59af4891333db4179448682a8f314464..fae3c3af61bf01f02c41f72f1978ff7036513671 100644 (file)
@@ -49,7 +49,7 @@ fn classify<'a, Ty, C>(
         let mut c = match layout.abi {
             Abi::Uninhabited => return Ok(()),
 
-            Abi::Scalar(ref scalar) => match scalar.value {
+            Abi::Scalar(scalar) => match scalar.value {
                 abi::Int(..) | abi::Pointer => Class::Int,
                 abi::F32 | abi::F64 => Class::Sse,
             },
index b0ecd117dd20e89b4016bcb6660cfc9cb19e9e9a..616071592087da8a5573884bdc47b851bcd78ab3 100644 (file)
@@ -7,7 +7,7 @@
 use std::fmt;
 use std::iter::Step;
 use std::num::NonZeroUsize;
-use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use rustc_index::vec::{Idx, IndexVec};
@@ -392,6 +392,21 @@ pub fn truncate(self, value: u128) -> u128 {
         // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
         (value << shift) >> shift
     }
+
+    #[inline]
+    pub fn signed_int_min(&self) -> i128 {
+        self.sign_extend(1_u128 << (self.bits() - 1)) as i128
+    }
+
+    #[inline]
+    pub fn signed_int_max(&self) -> i128 {
+        i128::MAX >> (128 - self.bits())
+    }
+
+    #[inline]
+    pub fn unsigned_int_max(&self) -> u128 {
+        u128::MAX >> (128 - self.bits())
+    }
 }
 
 // Panicking addition, subtraction and multiplication for convenience.
@@ -739,9 +754,8 @@ pub fn is_int(self) -> bool {
 ///
 ///    254 (-2), 255 (-1), 0, 1, 2
 ///
-/// This is intended specifically to mirror LLVM’s `!range` metadata,
-/// semantics.
-#[derive(Clone, PartialEq, Eq, Hash)]
+/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub struct WrappingRange {
     pub start: u128,
@@ -759,13 +773,6 @@ pub fn contains(&self, v: u128) -> bool {
         }
     }
 
-    /// 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 {
@@ -779,17 +786,29 @@ pub fn with_end(mut self, end: u128) -> Self {
         self.end = end;
         self
     }
+
+    /// Returns `true` if `size` completely fills the range.
+    #[inline]
+    pub fn is_full_for(&self, size: Size) -> bool {
+        let max_value = size.unsigned_int_max();
+        debug_assert!(self.start <= max_value && self.end <= max_value);
+        self.start == (self.end.wrapping_add(1) & max_value)
+    }
 }
 
 impl fmt::Debug for WrappingRange {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "{}..={}", self.start, self.end)?;
+        if self.start > self.end {
+            write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
+        } else {
+            write!(fmt, "{}..={}", self.start, self.end)?;
+        }
         Ok(())
     }
 }
 
 /// Information about one scalar component of a Rust type.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
@@ -803,25 +822,16 @@ pub struct Scalar {
 impl Scalar {
     #[inline]
     pub fn is_bool(&self) -> bool {
-        matches!(self.value, Int(I8, false))
-            && matches!(self.valid_range, WrappingRange { start: 0, end: 1 })
+        matches!(
+            self,
+            Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }
+        )
     }
 
-    /// Returns the valid range as a `x..y` range.
-    ///
-    /// If `x` and `y` are equal, the range is full, not empty.
-    pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
-        // For a (max) value of -1, max will be `-1 as usize`, which overflows.
-        // However, that is fine here (it would still represent the full range),
-        // i.e., if the range is everything.
-        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;
-        assert_eq!(start, start & mask);
-        assert_eq!(end, end & mask);
-        start..(end.wrapping_add(1) & mask)
+    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
+    #[inline]
+    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
+        self.valid_range.is_full_for(self.value.size(cx))
     }
 }
 
@@ -960,7 +970,7 @@ impl AddressSpace {
 
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Abi {
     Uninhabited,
     Scalar(Scalar),
@@ -988,8 +998,8 @@ 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 {
+        match self {
+            Abi::Scalar(scal) => match scal.value {
                 Primitive::Int(_, signed) => signed,
                 _ => false,
             },
@@ -1058,7 +1068,7 @@ pub enum TagEncoding {
     },
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Niche {
     pub offset: Size,
     pub scalar: Scalar,
@@ -1071,10 +1081,10 @@ pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Op
     }
 
     pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
-        let Scalar { value, valid_range: ref v } = self.scalar;
-        let bits = value.size(cx).bits();
-        assert!(bits <= 128);
-        let max_value = !0u128 >> (128 - bits);
+        let Scalar { value, valid_range: v } = self.scalar;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
 
         // Find out how many values are outside the valid range.
         let niche = v.end.wrapping_add(1)..v.start;
@@ -1084,24 +1094,58 @@ pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
         assert!(count > 0);
 
-        let Scalar { value, valid_range: v } = self.scalar.clone();
-        let bits = value.size(cx).bits();
-        assert!(bits <= 128);
-        let max_value = !0u128 >> (128 - bits);
+        let Scalar { value, valid_range: v } = self.scalar;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
 
-        if count > max_value {
+        let niche = v.end.wrapping_add(1)..v.start;
+        let available = niche.end.wrapping_sub(niche.start) & max_value;
+        if count > available {
             return None;
         }
 
-        // 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 v.contains(end) {
-            return None;
+        // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
+        // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
+        // This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
+        // Having `None` in niche zero can enable some special optimizations.
+        //
+        // Bound selection criteria:
+        // 1. Select closest to zero given wrapping semantics.
+        // 2. Avoid moving past zero if possible.
+        //
+        // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
+        // If niche zero is already reserved, the selection of bounds are of little interest.
+        let move_start = |v: WrappingRange| {
+            let start = v.start.wrapping_sub(1) & max_value;
+            Some((start, Scalar { value, valid_range: v.with_start(start) }))
+        };
+        let move_end = |v: WrappingRange| {
+            let start = v.end.wrapping_add(1) & max_value;
+            let end = v.end.wrapping_add(count) & max_value;
+            Some((start, Scalar { value, valid_range: v.with_end(end) }))
+        };
+        let distance_end_zero = max_value - v.end;
+        if v.start > v.end {
+            // zero is unavailable because wrapping occurs
+            move_end(v)
+        } else if v.start <= distance_end_zero {
+            if count <= v.start {
+                move_start(v)
+            } else {
+                // moved past zero, use other bound
+                move_end(v)
+            }
+        } else {
+            let end = v.end.wrapping_add(count) & max_value;
+            let overshot_zero = (1..=v.end).contains(&end);
+            if overshot_zero {
+                // moved past zero, use other bound
+                move_start(v)
+            } else {
+                move_end(v)
+            }
         }
-
-        Some((start, Scalar { value, valid_range: v.with_end(end) }))
     }
 }
 
@@ -1138,7 +1182,7 @@ pub struct Layout {
 
 impl Layout {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
-        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone());
+        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
         Layout {
@@ -1264,25 +1308,22 @@ pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
         Ty: TyAbiInterface<'a, C>,
         C: HasDataLayout,
     {
-        let scalar_allows_raw_init = move |s: &Scalar| -> bool {
+        let scalar_allows_raw_init = move |s: Scalar| -> bool {
             if zero {
                 // The range must contain 0.
-                s.valid_range.contains_zero()
+                s.valid_range.contains(0)
             } else {
-                // The range must include all values. `valid_range_exclusive` handles
-                // the wrap-around using target arithmetic; with wrap-around then the full
-                // range is one where `start == end`.
-                let range = s.valid_range_exclusive(cx);
-                range.start == range.end
+                // The range must include all values.
+                s.is_always_valid(cx)
             }
         };
 
         // Check the ABI.
-        let valid = match &self.abi {
+        let valid = match self.abi {
             Abi::Uninhabited => false, // definitely UB
             Abi::Scalar(s) => scalar_allows_raw_init(s),
             Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
-            Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
+            Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
             Abi::Aggregate { .. } => true, // Fields are checked below.
         };
         if !valid {
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
new file mode 100644 (file)
index 0000000..01f5c19
--- /dev/null
@@ -0,0 +1,43 @@
+use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+/// A base target for Nintendo 3DS devices using the devkitARM toolchain.
+///
+/// Requires the devkitARM toolchain for 3DS targets on the host system.
+
+pub fn target() -> Target {
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            "-specs=3dsx.specs".to_string(),
+            "-mtune=mpcore".to_string(),
+            "-mfloat-abi=hard".to_string(),
+            "-mtp=soft".to_string(),
+        ],
+    );
+
+    Target {
+        llvm_target: "armv6k-none-eabihf".to_string(),
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+
+        options: TargetOptions {
+            os: "horizon".to_string(),
+            env: "newlib".to_string(),
+            vendor: "nintendo".to_string(),
+            abi: "eabihf".to_string(),
+            linker_flavor: LinkerFlavor::Gcc,
+            cpu: "mpcore".to_string(),
+            executables: true,
+            families: vec!["unix".to_string()],
+            linker: Some("arm-none-eabi-gcc".to_string()),
+            relocation_model: RelocModel::Static,
+            features: "+vfp2".to_string(),
+            pre_link_args,
+            exe_suffix: ".elf".to_string(),
+            panic_strategy: PanicStrategy::Abort,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs
new file mode 100644 (file)
index 0000000..fff7b25
--- /dev/null
@@ -0,0 +1,15 @@
+use crate::abi::Endian;
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.max_atomic_width = Some(32);
+
+    Target {
+        llvm_target: "m68k-unknown-linux-gnu".to_string(),
+        pointer_width: 32,
+        data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".to_string(),
+        arch: "m68k".to_string(),
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
+    }
+}
index 273221360b8b561ca9d1d5d265956861369f6488..c947721d63d39bf5f0d9c98fcb0c1dbbfc75ac44 100644 (file)
@@ -742,6 +742,7 @@ fn $module() {
     ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
+    ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
     ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
     ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
@@ -941,6 +942,8 @@ fn $module() {
 
     ("bpfeb-unknown-none", bpfeb_unknown_none),
     ("bpfel-unknown-none", bpfel_unknown_none),
+
+    ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
 }
 
 /// Warnings encountered when parsing the target `json`.
index e2c626d1b22071b0e6f0f6e705f69e5e9fe15a37..9a9737362c6c8017bd8063e4b3a6b5ab1704ad4a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_trait_selection"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index c90649353e80f391b5739378a3bd29813bd5e22f..42cbed600d5bf92229ca6f6ff55002ded9d53d2c 100644 (file)
@@ -2,6 +2,7 @@
 use crate::traits::query::outlives_bounds::InferCtxtExt as _;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -184,7 +185,7 @@ pub trait OutlivesEnvironmentExt<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
         body_id: hir::HirId,
         span: Span,
     );
@@ -210,13 +211,13 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
         body_id: hir::HirId,
         span: Span,
     ) {
         debug!("add_implied_bounds()");
 
-        for &ty in fn_sig_tys {
+        for ty in fn_sig_tys {
             let ty = infcx.resolve_vars_if_possible(ty);
             debug!("add_implied_bounds: ty = {}", ty);
             let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
index b743c809ca2434926b49c0f80ee205744d366cd5..c01faae5d6a51c039f088df9aff6f0a7b5e782a7 100644 (file)
@@ -1,4 +1,3 @@
-use crate::infer::InferCtxtExt as _;
 use crate::traits::{self, ObligationCause, PredicateObligation};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
@@ -499,7 +498,7 @@ fn generate_member_constraint(
     /// - `substs`, the substs  used to instantiate this opaque type
     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
     ///   `opaque_defn.concrete_ty`
-    #[instrument(skip(self))]
+    #[instrument(level = "debug", skip(self))]
     fn infer_opaque_definition_from_instantiation(
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
@@ -863,7 +862,6 @@ struct Instantiator<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Instantiator<'a, 'tcx> {
-    #[instrument(skip(self))]
     fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
         let tcx = self.infcx.tcx;
         value.fold_with(&mut BottomUpFolder {
@@ -954,6 +952,7 @@ fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -
         })
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn fold_opaque_ty(
         &mut self,
         ty: Ty<'tcx>,
@@ -964,25 +963,18 @@ fn fold_opaque_ty(
         let tcx = infcx.tcx;
         let OpaqueTypeKey { def_id, substs } = opaque_type_key;
 
-        debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
-
         // Use the same type variable if the exact same opaque type appears more
         // than once in the return type (e.g., if it's passed to a type alias).
         if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
-            debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
+            debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
             return opaque_defn.concrete_ty;
         }
+
         let ty_var = infcx.next_ty_var(TypeVariableOrigin {
             kind: TypeVariableOriginKind::TypeInference,
             span: self.value_span,
         });
 
-        // Make sure that we are in fact defining the *entire* type
-        // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
-        // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
-        debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
-        debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
-
         // Ideally, we'd get the span where *this specific `ty` came
         // from*, but right now we just use the span from the overall
         // value being folded. In simple cases like `-> impl Foo`,
@@ -999,43 +991,40 @@ fn fold_opaque_ty(
             infcx.opaque_types_vars.insert(ty_var, ty);
         }
 
-        debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
-        self.compute_opaque_type_obligations(opaque_type_key);
-
-        ty_var
-    }
-
-    fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) {
-        let infcx = self.infcx;
-        let tcx = infcx.tcx;
-        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+        debug!("generated new type inference var {:?}", ty_var.kind());
 
         let item_bounds = tcx.explicit_item_bounds(def_id);
-        debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
-        let bounds: Vec<_> =
-            item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
-
-        let param_env = tcx.param_env(def_id);
-        let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
-            ObligationCause::misc(self.value_span, self.body_id),
-            param_env,
-            bounds,
-        );
-        self.obligations.extend(obligations);
 
-        debug!("instantiate_opaque_types: bounds={:?}", bounds);
+        self.obligations.reserve(item_bounds.len());
+        for (predicate, _) in item_bounds {
+            debug!(?predicate);
+            let predicate = predicate.subst(tcx, substs);
+            debug!(?predicate);
+
+            // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
+            let predicate = predicate.fold_with(&mut BottomUpFolder {
+                tcx,
+                ty_op: |ty| match ty.kind() {
+                    ty::Projection(projection_ty) => infcx.infer_projection(
+                        self.param_env,
+                        *projection_ty,
+                        ObligationCause::misc(self.value_span, self.body_id),
+                        0,
+                        &mut self.obligations,
+                    ),
+                    _ => ty,
+                },
+                lt_op: |lt| lt,
+                ct_op: |ct| ct,
+            });
+            debug!(?predicate);
 
-        for predicate in &bounds {
             if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
                 if projection.ty.references_error() {
                     // No point on adding these obligations since there's a type error involved.
-                    return;
+                    return tcx.ty_error();
                 }
             }
-        }
-
-        self.obligations.reserve(bounds.len());
-        for predicate in bounds {
             // Change the predicate to refer to the type variable,
             // which will be the concrete type instead of the opaque type.
             // This also instantiates nested instances of `impl Trait`.
@@ -1045,9 +1034,11 @@ fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tc
                 traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
 
             // Require that the predicate holds for the concrete type.
-            debug!("instantiate_opaque_types: predicate={:?}", predicate);
+            debug!(?predicate);
             self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
         }
+
+        ty_var
     }
 }
 
index 7a690af0cc6e5e78e49a3dfc645979438e41c6ce..9c962d30ce0e8b8a575627173b019c993dee5b16 100644 (file)
@@ -57,7 +57,6 @@ fn select_all_or_error(
                 .map(|obligation| FulfillmentError {
                     obligation: obligation.clone(),
                     code: FulfillmentErrorCode::CodeAmbiguity,
-                    points_at_arg_span: false,
                     // FIXME - does Chalk have a notation of 'root obligation'?
                     // This is just for diagnostics, so it's okay if this is wrong
                     root_obligation: obligation.clone(),
@@ -112,7 +111,6 @@ fn select_where_possible(
                                     code: FulfillmentErrorCode::CodeSelectionError(
                                         SelectionError::Unimplemented,
                                     ),
-                                    points_at_arg_span: false,
                                     // FIXME - does Chalk have a notation of 'root obligation'?
                                     // This is just for diagnostics, so it's okay if this is wrong
                                     root_obligation: obligation,
@@ -129,7 +127,6 @@ fn select_where_possible(
                         code: FulfillmentErrorCode::CodeSelectionError(
                             SelectionError::Unimplemented,
                         ),
-                        points_at_arg_span: false,
                         // FIXME - does Chalk have a notation of 'root obligation'?
                         // This is just for diagnostics, so it's okay if this is wrong
                         root_obligation: obligation,
index ddabe5967d79cf9566fd923249ce4bfcc4658bae..24fa5007f1ecdc446f528a307edd28f11ec0efd7 100644 (file)
@@ -6,16 +6,16 @@
 //! this is not as easy.
 //!
 //! In this case we try to build an abstract representation of this constant using
-//! `mir_abstract_const` which can then be checked for structural equality with other
+//! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
 use rustc_errors::ErrorReported;
 use rustc_hir::def::DefKind;
-use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
-use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable};
+use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
+use rustc_middle::thir;
+use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_session::lint;
@@ -196,7 +196,7 @@ pub fn new(
         tcx: TyCtxt<'tcx>,
         uv: ty::Unevaluated<'tcx, ()>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
-        let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?;
+        let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
         debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
         Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) }))
     }
@@ -223,35 +223,24 @@ pub fn root(self) -> Node<'tcx> {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-struct WorkNode<'tcx> {
-    node: Node<'tcx>,
-    span: Span,
-    used: bool,
-}
-
 struct AbstractConstBuilder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'a mir::Body<'tcx>,
+    body_id: thir::ExprId,
+    body: &'a thir::Thir<'tcx>,
     /// The current WIP node tree.
-    ///
-    /// We require all nodes to be used in the final abstract const,
-    /// so we store this here. Note that we also consider nodes as used
-    /// if they are mentioned in an assert, so some used nodes are never
-    /// actually reachable by walking the [`AbstractConst`].
-    nodes: IndexVec<NodeId, WorkNode<'tcx>>,
-    locals: IndexVec<mir::Local, NodeId>,
-    /// We only allow field accesses if they access
-    /// the result of a checked operation.
-    checked_op_locals: BitSet<mir::Local>,
+    nodes: IndexVec<NodeId, Node<'tcx>>,
 }
 
 impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
+    fn root_span(&self) -> Span {
+        self.body.exprs[self.body_id].span
+    }
+
     fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
         self.tcx
             .sess
-            .struct_span_err(self.body.span, "overly complex generic constant")
-            .span_label(span.unwrap_or(self.body.span), msg)
+            .struct_span_err(self.root_span(), "overly complex generic constant")
+            .span_label(span.unwrap_or(self.root_span()), msg)
             .help("consider moving this anonymous constant into a `const` function")
             .emit();
 
@@ -260,98 +249,49 @@ fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
 
     fn new(
         tcx: TyCtxt<'tcx>,
-        body: &'a mir::Body<'tcx>,
+        (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId),
     ) -> Result<Option<AbstractConstBuilder<'a, 'tcx>>, ErrorReported> {
-        let mut builder = AbstractConstBuilder {
-            tcx,
-            body,
-            nodes: IndexVec::new(),
-            locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls),
-            checked_op_locals: BitSet::new_empty(body.local_decls.len()),
-        };
-
-        // We don't have to look at concrete constants, as we
-        // can just evaluate them.
-        if !body.is_polymorphic {
-            return Ok(None);
-        }
+        let builder = AbstractConstBuilder { tcx, body_id, body, nodes: IndexVec::new() };
 
-        // We only allow consts without control flow, so
-        // we check for cycles here which simplifies the
-        // rest of this implementation.
-        if body.is_cfg_cyclic() {
-            builder.error(None, "cyclic anonymous constants are forbidden")?;
+        struct IsThirPolymorphic<'a, 'tcx> {
+            is_poly: bool,
+            thir: &'a thir::Thir<'tcx>,
+            tcx: TyCtxt<'tcx>,
         }
 
-        Ok(Some(builder))
-    }
-
-    fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId {
-        // Mark used nodes.
-        match node {
-            Node::Leaf(_) => (),
-            Node::Binop(_, lhs, rhs) => {
-                self.nodes[lhs].used = true;
-                self.nodes[rhs].used = true;
-            }
-            Node::UnaryOp(_, input) => {
-                self.nodes[input].used = true;
-            }
-            Node::FunctionCall(func, nodes) => {
-                self.nodes[func].used = true;
-                nodes.iter().for_each(|&n| self.nodes[n].used = true);
+        use thir::visit;
+        impl<'a, 'tcx: 'a> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
+            fn thir(&self) -> &'a thir::Thir<'tcx> {
+                &self.thir
             }
-            Node::Cast(_, operand, _) => {
-                self.nodes[operand].used = true;
+
+            fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) {
+                self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx);
+                if self.is_poly == false {
+                    visit::walk_expr(self, expr)
+                }
             }
-        }
 
-        // Nodes start as unused.
-        self.nodes.push(WorkNode { node, span, used: false })
-    }
+            fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
+                self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx);
+                if self.is_poly == false {
+                    visit::walk_pat(self, pat);
+                }
+            }
 
-    fn place_to_local(
-        &mut self,
-        span: Span,
-        p: &mir::Place<'tcx>,
-    ) -> Result<mir::Local, ErrorReported> {
-        const ZERO_FIELD: mir::Field = mir::Field::from_usize(0);
-        // Do not allow any projections.
-        //
-        // One exception are field accesses on the result of checked operations,
-        // which are required to support things like `1 + 2`.
-        if let Some(p) = p.as_local() {
-            debug_assert!(!self.checked_op_locals.contains(p));
-            Ok(p)
-        } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
-            // Only allow field accesses if the given local
-            // contains the result of a checked operation.
-            if self.checked_op_locals.contains(p.local) {
-                Ok(p.local)
-            } else {
-                self.error(Some(span), "unsupported projection")?;
+            fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) {
+                self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx);
             }
-        } else {
-            self.error(Some(span), "unsupported projection")?;
         }
-    }
 
-    fn operand_to_node(
-        &mut self,
-        span: Span,
-        op: &mir::Operand<'tcx>,
-    ) -> Result<NodeId, ErrorReported> {
-        debug!("operand_to_node: op={:?}", op);
-        match op {
-            mir::Operand::Copy(p) | mir::Operand::Move(p) => {
-                let local = self.place_to_local(span, p)?;
-                Ok(self.locals[local])
-            }
-            mir::Operand::Constant(ct) => match ct.literal {
-                mir::ConstantKind::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)),
-                mir::ConstantKind::Val(..) => self.error(Some(span), "unsupported constant")?,
-            },
+        let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx };
+        visit::walk_expr(&mut is_poly_vis, &body[body_id]);
+        debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly);
+        if is_poly_vis.is_poly == false {
+            return Ok(None);
         }
+
+        Ok(Some(builder))
     }
 
     /// We do not allow all binary operations in abstract consts, so filter disallowed ones.
@@ -373,170 +313,126 @@ fn check_unop(op: mir::UnOp) -> bool {
         }
     }
 
-    fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> {
-        debug!("AbstractConstBuilder: stmt={:?}", stmt);
-        let span = stmt.source_info.span;
-        match stmt.kind {
-            StatementKind::Assign(box (ref place, ref rvalue)) => {
-                let local = self.place_to_local(span, place)?;
-                match *rvalue {
-                    Rvalue::Use(ref operand) => {
-                        self.locals[local] = self.operand_to_node(span, operand)?;
-                        Ok(())
-                    }
-                    Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) if Self::check_binop(op) => {
-                        let lhs = self.operand_to_node(span, lhs)?;
-                        let rhs = self.operand_to_node(span, rhs)?;
-                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
-                        if op.is_checkable() {
-                            bug!("unexpected unchecked checkable binary operation");
-                        } else {
-                            Ok(())
-                        }
-                    }
-                    Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs))
-                        if Self::check_binop(op) =>
-                    {
-                        let lhs = self.operand_to_node(span, lhs)?;
-                        let rhs = self.operand_to_node(span, rhs)?;
-                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
-                        self.checked_op_locals.insert(local);
-                        Ok(())
-                    }
-                    Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
-                        let operand = self.operand_to_node(span, operand)?;
-                        self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
-                        Ok(())
-                    }
-                    Rvalue::Cast(cast_kind, ref operand, ty) => {
-                        let operand = self.operand_to_node(span, operand)?;
-                        self.locals[local] =
-                            self.add_node(Node::Cast(cast_kind, operand, ty), span);
-                        Ok(())
-                    }
-                    _ => self.error(Some(span), "unsupported rvalue")?,
-                }
-            }
-            // These are not actually relevant for us here, so we can ignore them.
-            StatementKind::AscribeUserType(..)
-            | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_) => Ok(()),
-            _ => self.error(Some(stmt.source_info.span), "unsupported statement")?,
-        }
-    }
-
-    /// Possible return values:
-    ///
-    /// - `None`: unsupported terminator, stop building
-    /// - `Some(None)`: supported terminator, finish building
-    /// - `Some(Some(block))`: support terminator, build `block` next
-    fn build_terminator(
-        &mut self,
-        terminator: &mir::Terminator<'tcx>,
-    ) -> Result<Option<mir::BasicBlock>, ErrorReported> {
-        debug!("AbstractConstBuilder: terminator={:?}", terminator);
-        match terminator.kind {
-            TerminatorKind::Goto { target } => Ok(Some(target)),
-            TerminatorKind::Return => Ok(None),
-            TerminatorKind::Call {
-                ref func,
-                ref args,
-                destination: Some((ref place, target)),
-                // We do not care about `cleanup` here. Any branch which
-                // uses `cleanup` will fail const-eval and they therefore
-                // do not matter when checking for const evaluatability.
-                //
-                // Do note that even if `panic::catch_unwind` is made const,
-                // we still do not have to care about this, as we do not look
-                // into functions.
-                cleanup: _,
-                // Do not allow overloaded operators for now,
-                // we probably do want to allow this in the future.
-                //
-                // This is currently fairly irrelevant as it requires `const Trait`s.
-                from_hir_call: true,
-                fn_span,
-            } => {
-                let local = self.place_to_local(fn_span, place)?;
-                let func = self.operand_to_node(fn_span, func)?;
-                let args = self.tcx.arena.alloc_from_iter(
-                    args.iter()
-                        .map(|arg| self.operand_to_node(terminator.source_info.span, arg))
-                        .collect::<Result<Vec<NodeId>, _>>()?,
-                );
-                self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span);
-                Ok(Some(target))
-            }
-            TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
-                let p = match cond {
-                    mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
-                    mir::Operand::Constant(_) => bug!("unexpected assert"),
-                };
-
-                const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
-                debug!("proj: {:?}", p.projection);
-                if let Some(p) = p.as_local() {
-                    debug_assert!(!self.checked_op_locals.contains(p));
-                    // Mark locals directly used in asserts as used.
-                    //
-                    // This is needed because division does not use `CheckedBinop` but instead
-                    // adds an explicit assert for `divisor != 0`.
-                    self.nodes[self.locals[p]].used = true;
-                    return Ok(Some(target));
-                } else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
-                    // Only allow asserts checking the result of a checked operation.
-                    if self.checked_op_locals.contains(p.local) {
-                        return Ok(Some(target));
-                    }
-                }
-
-                self.error(Some(terminator.source_info.span), "unsupported assertion")?;
-            }
-            _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?,
-        }
-    }
-
-    /// Builds the abstract const by walking the mir from start to finish
-    /// and bailing out when encountering an unsupported operation.
+    /// Builds the abstract const by walking the thir and bailing out when
+    /// encountering an unspported operation.
     fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> {
-        let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
-        // We checked for a cyclic cfg above, so this should terminate.
-        loop {
-            debug!("AbstractConstBuilder: block={:?}", block);
-            for stmt in block.statements.iter() {
-                self.build_statement(stmt)?;
-            }
+        debug!("Abstractconstbuilder::build: body={:?}", &*self.body);
+        self.recurse_build(self.body_id)?;
 
-            if let Some(next) = self.build_terminator(block.terminator())? {
-                block = &self.body.basic_blocks()[next];
-            } else {
-                break;
-            }
-        }
-
-        assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
         for n in self.nodes.iter() {
-            if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node {
+            if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n {
                 // `AbstractConst`s should not contain any promoteds as they require references which
                 // are not allowed.
                 assert_eq!(ct.promoted, None);
             }
         }
 
-        self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
-        if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
-            self.error(Some(unused.span), "dead code")?;
-        }
+        Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter()))
+    }
 
-        Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)))
+    fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorReported> {
+        use thir::ExprKind;
+        let node = &self.body.exprs[node];
+        debug!("recurse_build: node={:?}", node);
+        Ok(match &node.kind {
+            // I dont know if handling of these 3 is correct
+            &ExprKind::Scope { value, .. } => self.recurse_build(value)?,
+            &ExprKind::PlaceTypeAscription { source, .. } |
+            &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
+
+            // subtle: associated consts are literals this arm handles
+            // `<T as Trait>::ASSOC` as well as `12`
+            &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
+
+            ExprKind::Call { fun, args,  .. } => {
+                let fun = self.recurse_build(*fun)?;
+
+                let mut new_args = Vec::<NodeId>::with_capacity(args.len());
+                for &id in args.iter() {
+                    new_args.push(self.recurse_build(id)?);
+                }
+                let new_args = self.tcx.arena.alloc_slice(&new_args);
+                self.nodes.push(Node::FunctionCall(fun, new_args))
+            },
+            &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
+                let lhs = self.recurse_build(lhs)?;
+                let rhs = self.recurse_build(rhs)?;
+                self.nodes.push(Node::Binop(op, lhs, rhs))
+            }
+            &ExprKind::Unary { op, arg } if Self::check_unop(op) => {
+                let arg = self.recurse_build(arg)?;
+                self.nodes.push(Node::UnaryOp(op, arg))
+            },
+            // This is necessary so that the following compiles:
+            //
+            // ```
+            // fn foo<const N: usize>(a: [(); N + 1]) {
+            //     bar::<{ N + 1 }>();
+            // }
+            // ```
+            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
+            // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
+            // "coercion cast" i.e. using a coercion or is a no-op.
+            // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
+            &ExprKind::Use { source } => {
+                let arg = self.recurse_build(source)?;
+                self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
+            },
+            &ExprKind::Cast { source } => {
+                let arg = self.recurse_build(source)?;
+                self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
+            },
+
+            // FIXME(generic_const_exprs): We may want to support these.
+            ExprKind::AddressOf { .. }
+            | ExprKind::Borrow { .. }
+            | ExprKind::Deref { .. }
+            | ExprKind::Repeat { .. }
+            | ExprKind::Array { .. }
+            | ExprKind::Block { .. }
+            | ExprKind::NeverToAny { .. }
+            | ExprKind::Tuple { .. }
+            | ExprKind::Index { .. }
+            | ExprKind::Field { .. }
+            | ExprKind::ConstBlock { .. }
+            | ExprKind::Adt(_) => self.error(
+                    Some(node.span),
+                    "unsupported operation in generic constant, this may be supported in the future",
+                )?,
+
+            ExprKind::Match { .. }
+            // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
+            | ExprKind::VarRef { .. }
+            | ExprKind::UpvarRef { .. }
+            | ExprKind::Closure { .. }
+            | ExprKind::Let { .. } // let expressions imply control flow
+            | ExprKind::Loop { .. }
+            | ExprKind::Assign { .. }
+            | ExprKind::StaticRef { .. }
+            | ExprKind::LogicalOp { .. }
+            // we handle valid unary/binary ops above
+            | ExprKind::Unary { .. }
+            | ExprKind::Binary { .. }
+            | ExprKind::Break { .. }
+            | ExprKind::Continue { .. }
+            | ExprKind::If { .. }
+            | ExprKind::Pointer { .. } // dont know if this is correct
+            | ExprKind::ThreadLocalRef(_)
+            | ExprKind::LlvmInlineAsm { .. }
+            | ExprKind::Return { .. }
+            | ExprKind::Box { .. } // allocations not allowed in constants
+            | ExprKind::AssignOp { .. }
+            | ExprKind::InlineAsm { .. }
+            | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
+        })
     }
 }
 
 /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
-pub(super) fn mir_abstract_const<'tcx>(
+pub(super) fn thir_abstract_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
     if tcx.features().generic_const_exprs {
         match tcx.def_kind(def.did) {
             // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
@@ -547,8 +443,16 @@ pub(super) fn mir_abstract_const<'tcx>(
             DefKind::AnonConst => (),
             _ => return Ok(None),
         }
-        let body = tcx.mir_const(def).borrow();
-        AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose()
+
+        let body = tcx.thir_body(def);
+        if body.0.borrow().exprs.is_empty() {
+            // type error in constant, there is no thir
+            return Err(ErrorReported);
+        }
+
+        AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
+            .map(AbstractConstBuilder::build)
+            .transpose()
     } else {
         Ok(None)
     }
@@ -682,11 +586,16 @@ pub(super) fn try_unify<'tcx>(
                 && iter::zip(a_args, b_args)
                     .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
         }
-        (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
-            if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
+        (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty))
+            if (a_ty == b_ty) && (a_kind == b_kind) =>
         {
             try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
         }
-        _ => false,
+        // use this over `_ => false` to make adding variants to `Node` less error prone
+        (Node::Cast(..), _)
+        | (Node::FunctionCall(..), _)
+        | (Node::UnaryOp(..), _)
+        | (Node::Binop(..), _)
+        | (Node::Leaf(..), _) => false,
     }
 }
index 9ce6c58a0f1df4b81b08fbb494dff3458169a230..e435154d9318e7b087a7bc98c84097b4f3e51b64 100644 (file)
@@ -19,7 +19,7 @@
 use rustc_hir::GenericParam;
 use rustc_hir::Item;
 use rustc_hir::Node;
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{
@@ -66,7 +66,6 @@ fn report_selection_error(
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
-        points_at_arg: bool,
     );
 
     /// Given some node representing a fn-like thing in the HIR map,
@@ -237,7 +236,6 @@ fn report_selection_error(
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
-        points_at_arg: bool,
     ) {
         let tcx = self.tcx;
         let mut span = obligation.cause.span;
@@ -249,10 +247,10 @@ fn report_selection_error(
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code.peel_derives()
                 {
-                    if let Some(cause) = self.tcx.diagnostic_hir_wf_check((
-                        tcx.erase_regions(obligation.predicate),
-                        wf_loc.clone(),
-                    )) {
+                    if let Some(cause) = self
+                        .tcx
+                        .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
+                    {
                         obligation.cause = cause;
                         span = obligation.cause.span;
                     }
@@ -387,7 +385,6 @@ fn report_selection_error(
                             &obligation,
                             &mut err,
                             &trait_ref,
-                            points_at_arg,
                             have_alt_message,
                         ) {
                             self.note_obligation_cause(&mut err, &obligation);
@@ -430,8 +427,8 @@ fn report_selection_error(
                             err.span_label(enclosing_scope_span, s.as_str());
                         }
 
-                        self.suggest_dereferences(&obligation, &mut err, trait_ref, points_at_arg);
-                        self.suggest_fn_call(&obligation, &mut err, trait_ref, points_at_arg);
+                        self.suggest_dereferences(&obligation, &mut err, trait_ref);
+                        self.suggest_fn_call(&obligation, &mut err, trait_ref);
                         self.suggest_remove_reference(&obligation, &mut err, trait_ref);
                         self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref);
                         self.note_version_mismatch(&mut err, &trait_ref);
@@ -500,12 +497,7 @@ fn report_selection_error(
                         // Changing mutability doesn't make a difference to whether we have
                         // an `Unsize` impl (Fixes ICE in #71036)
                         if !is_unsize {
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                trait_ref,
-                                points_at_arg,
-                            );
+                            self.suggest_change_mut(&obligation, &mut err, trait_ref);
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
@@ -730,7 +722,10 @@ fn report_selection_error(
                 };
 
                 let found_did = match *found_trait_ty.kind() {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Closure(did, _)
+                    | ty::Foreign(did)
+                    | ty::FnDef(did, _)
+                    | ty::Generator(did, ..) => Some(did),
                     ty::Adt(def, _) => Some(def.did),
                     _ => None,
                 };
@@ -1214,7 +1209,6 @@ fn report_fulfillment_error(
                     &error.root_obligation,
                     selection_error,
                     fallback_has_occurred,
-                    error.points_at_arg_span,
                 );
             }
             FulfillmentErrorCode::CodeProjectionError(ref e) => {
index 3a32f1cb903e583f24117db65fc84197e2aa3b84..6128c119b6b765568a68dc692cccdfca332c368f 100644 (file)
@@ -154,9 +154,6 @@ fn on_unimplemented_note(
                 flags.push((sym::from_method, Some(method.to_string())));
             }
         }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
 
         if let Some(k) = obligation.cause.span.desugaring_kind() {
             flags.push((sym::from_desugaring, None));
index 0d3fd748645edb266980aa635a32a72f011529d5..ae61988928f78e6ba2f317016718c2cf1df01c3f 100644 (file)
@@ -9,6 +9,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -23,7 +24,7 @@
 use rustc_middle::ty::{TypeAndMut, TypeckResults};
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use std::fmt;
 
@@ -54,7 +55,6 @@ fn suggest_dereferences(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-        points_at_arg: bool,
     );
 
     fn get_closure_name(
@@ -69,7 +69,6 @@ fn suggest_fn_call(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     );
 
     fn suggest_add_reference_to_arg(
@@ -77,7 +76,6 @@ fn suggest_add_reference_to_arg(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
         has_custom_message: bool,
     ) -> bool;
 
@@ -93,7 +91,6 @@ fn suggest_change_mut(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     );
 
     fn suggest_semicolon_removal(
@@ -490,16 +487,19 @@ fn suggest_dereferences(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-        points_at_arg: bool,
     ) {
         // It only make sense when suggesting dereferences for arguments
-        if !points_at_arg {
+        let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+            &obligation.cause.code
+        {
+            parent_code.clone()
+        } else {
             return;
-        }
+        };
         let param_env = obligation.param_env;
         let body_id = obligation.cause.body_id;
         let span = obligation.cause.span;
-        let real_trait_ref = match &obligation.cause.code {
+        let real_trait_ref = match &*code {
             ObligationCauseCode::ImplDerivedObligation(cause)
             | ObligationCauseCode::DerivedObligation(cause)
             | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref,
@@ -584,7 +584,6 @@ fn suggest_fn_call(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     ) {
         let self_ty = match trait_ref.self_ty().no_bound_vars() {
             None => return,
@@ -656,11 +655,11 @@ fn suggest_fn_call(
             }
             _ => return,
         };
-        if points_at_arg {
+        if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) {
             // When the obligation error has been ensured to have been caused by
             // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
+            // of the argument, so we can provide a suggestion. Otherwise, we give
+            // a more general note.
             err.span_suggestion_verbose(
                 obligation.cause.span.shrink_to_hi(),
                 &msg,
@@ -677,12 +676,21 @@ fn suggest_add_reference_to_arg(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
         has_custom_message: bool,
     ) -> bool {
-        if !points_at_arg {
+        let span = obligation.cause.span;
+
+        let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+            &obligation.cause.code
+        {
+            parent_code.clone()
+        } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) =
+            span.ctxt().outer_expn_data().kind
+        {
+            Lrc::new(obligation.cause.code.clone())
+        } else {
             return false;
-        }
+        };
 
         // List of traits for which it would be nonsensical to suggest borrowing.
         // For instance, immutable references are always Copy, so suggesting to
@@ -695,7 +703,6 @@ fn suggest_add_reference_to_arg(
 
         never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
 
-        let span = obligation.cause.span;
         let param_env = obligation.param_env;
         let trait_ref = trait_ref.skip_binder();
 
@@ -754,7 +761,11 @@ fn suggest_add_reference_to_arg(
                     );
 
                     // This if is to prevent a special edge-case
-                    if !span.from_expansion() {
+                    if matches!(
+                        span.ctxt().outer_expn_data().kind,
+                        ExpnKind::Root
+                            | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
+                    ) {
                         // We don't want a borrowing suggestion on the fields in structs,
                         // ```
                         // struct Foo {
@@ -778,7 +789,7 @@ fn suggest_add_reference_to_arg(
             return false;
         };
 
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
             let expected_trait_ref = obligation.parent_trait_ref.skip_binder();
             let new_imm_trait_ref =
                 ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
@@ -790,7 +801,7 @@ fn suggest_add_reference_to_arg(
                 return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]);
             }
         } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code
+        | ObligationCauseCode::ItemObligation(_) = &*code
         {
             if try_borrowing(
                 ty::TraitRef::new(trait_ref.def_id, imm_substs),
@@ -882,8 +893,12 @@ fn suggest_change_mut(
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     ) {
+        let points_at_arg = matches!(
+            obligation.cause.code,
+            ObligationCauseCode::FunctionArgumentObligation { .. },
+        );
+
         let span = obligation.cause.span;
         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
             let refs_number =
@@ -1241,33 +1256,40 @@ fn report_closure_arg_mismatch(
             trait_ref: ty::PolyTraitRef<'tcx>,
         ) -> String {
             let inputs = trait_ref.skip_binder().substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind() {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
-                    false,
-                    hir::Unsafety::Normal,
-                    abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
+            let sig = match inputs.kind() {
+                ty::Tuple(inputs)
+                    if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() =>
+                {
+                    tcx.mk_fn_sig(
+                        inputs.iter().map(|k| k.expect_ty()),
+                        tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
+                        false,
+                        hir::Unsafety::Normal,
+                        abi::Abi::Rust,
+                    )
+                }
+                _ => tcx.mk_fn_sig(
                     std::iter::once(inputs),
                     tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))),
                     false,
                     hir::Unsafety::Normal,
                     abi::Abi::Rust,
-                )
+                ),
             };
             trait_ref.rebind(sig).to_string()
         }
 
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let argument_kind = match expected_ref.skip_binder().substs.type_at(0) {
+            t if t.is_closure() => "closure",
+            t if t.is_generator() => "generator",
+            _ => "function",
+        };
         let mut err = struct_span_err!(
             self.tcx.sess,
             span,
             E0631,
             "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
+            argument_kind
         );
 
         let found_str = format!("expected signature of `{}`", build_fn_sig_string(self.tcx, found));
@@ -2280,6 +2302,56 @@ fn note_obligation_cause_code<T>(
                     )
                 });
             }
+            ObligationCauseCode::FunctionArgumentObligation {
+                arg_hir_id,
+                call_hir_id,
+                ref parent_code,
+            } => {
+                let hir = self.tcx.hir();
+                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
+                    hir.find(arg_hir_id)
+                {
+                    let in_progress_typeck_results =
+                        self.in_progress_typeck_results.map(|t| t.borrow());
+                    let parent_id = hir.local_def_id(hir.get_parent_item(arg_hir_id));
+                    let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results {
+                        Some(t) if t.hir_owner == parent_id => t,
+                        _ => self.tcx.typeck(parent_id),
+                    };
+                    let ty = typeck_results.expr_ty_adjusted(expr);
+                    let span = expr.peel_blocks().span;
+                    if Some(span) != err.span.primary_span() {
+                        err.span_label(
+                            span,
+                            &if ty.references_error() {
+                                String::new()
+                            } else {
+                                format!("this tail expression is of type `{:?}`", ty)
+                            },
+                        );
+                    }
+                }
+                if let Some(Node::Expr(hir::Expr {
+                    kind:
+                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                        | hir::ExprKind::MethodCall(_, span, ..),
+                    ..
+                })) = hir.find(call_hir_id)
+                {
+                    if Some(*span) != err.span.primary_span() {
+                        err.span_label(*span, "required by a bound introduced by this call");
+                    }
+                }
+                ensure_sufficient_stack(|| {
+                    self.note_obligation_cause_code(
+                        err,
+                        predicate,
+                        &parent_code,
+                        obligated_types,
+                        seen_requirements,
+                    )
+                });
+            }
             ObligationCauseCode::CompareImplMethodObligation {
                 item_name,
                 trait_item_def_id,
index 18abcc72bcee8d013950671b67c558c7f305c163..b376f4292924963574d690c85d6426119479fa89 100644 (file)
@@ -5,8 +5,8 @@
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::ToPredicate;
index 44c675243838a11e1213f6f5131af5edc5803db0..ef208c44471cbadf52d2b5dcdea6af83fc019092 100644 (file)
@@ -827,16 +827,16 @@ pub fn provide(providers: &mut ty::query::Providers) {
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
-        mir_abstract_const: |tcx, def_id| {
+        thir_abstract_const: |tcx, def_id| {
             let def_id = def_id.expect_local();
             if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-                tcx.mir_abstract_const_of_const_arg(def)
+                tcx.thir_abstract_const_of_const_arg(def)
             } else {
-                const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
+                const_evaluatable::thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
             }
         },
-        mir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
-            const_evaluatable::mir_abstract_const(
+        thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
+            const_evaluatable::thir_abstract_const(
                 tcx,
                 ty::WithOptConstParam { did, const_param_did: Some(param_did) },
             )
index 57b8a84300ff9e0db5464fc1759d913c0b6ae9c9..4922cf45a4a109565db5478fb7b53c8a3b5c3e8d 100644 (file)
@@ -465,9 +465,9 @@ fn virtual_call_violation_for_method<'tcx>(
 
             let param_env = tcx.param_env(method.def_id);
 
-            let abi_of_ty = |ty: Ty<'tcx>| -> Option<&Abi> {
+            let abi_of_ty = |ty: Ty<'tcx>| -> Option<Abi> {
                 match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => Some(&layout.abi),
+                    Ok(layout) => Some(layout.abi),
                     Err(err) => {
                         // #78372
                         tcx.sess.delay_span_bug(
@@ -836,7 +836,7 @@ fn visit_unevaluated_const(
             //
             // 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;
+            use rustc_middle::thir::abstract_const::Node;
             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) => {
index 7038f16a2c9c4032652964b9c2590f284706f675..58589e556f2704afddc37f790f6da59ae984c822 100644 (file)
@@ -595,7 +595,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
-                self.mapped_regions.insert(p.clone(), br);
+                self.mapped_regions.insert(p, br);
                 self.infcx.tcx.mk_region(ty::RePlaceholder(p))
             }
             _ => r,
@@ -613,7 +613,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderType { universe, name: bound_ty.var };
-                self.mapped_types.insert(p.clone(), bound_ty);
+                self.mapped_types.insert(p, bound_ty);
                 self.infcx.tcx.mk_ty(ty::Placeholder(p))
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
@@ -637,7 +637,7 @@ fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
                     universe,
                     name: ty::BoundConst { var: bound_const, ty },
                 };
-                self.mapped_consts.insert(p.clone(), bound_const);
+                self.mapped_consts.insert(p, bound_const);
                 self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
@@ -810,17 +810,7 @@ pub fn normalize_projection_type<'a, 'b, 'tcx>(
         // and a deferred predicate to resolve this when more type
         // information is available.
 
-        let tcx = selcx.infcx().tcx;
-        let def_id = projection_ty.item_def_id;
-        let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
-            kind: TypeVariableOriginKind::NormalizeProjectionType,
-            span: tcx.def_span(def_id),
-        });
-        let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
-        let obligation =
-            Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx));
-        obligations.push(obligation);
-        ty_var
+        selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations)
     })
 }
 
@@ -844,6 +834,10 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     obligations: &mut Vec<PredicateObligation<'tcx>>,
 ) -> Result<Option<Ty<'tcx>>, InProgress> {
     let infcx = selcx.infcx();
+    // Don't use the projection cache in intercrate mode -
+    // the `infcx` may be re-used between intercrate in non-intercrate
+    // mode, which could lead to using incorrect cache results.
+    let use_cache = !selcx.is_intercrate();
 
     let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
     let cache_key = ProjectionCacheKey::new(projection_ty);
@@ -856,7 +850,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
     // bounds. It might be the case that we want two distinct caches,
     // or else another kind of cache entry.
 
-    let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
+    let cache_result = if use_cache {
+        infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
+    } else {
+        Ok(())
+    };
     match cache_result {
         Ok(()) => debug!("no cache"),
         Err(ProjectionCacheEntry::Ambiguous) => {
@@ -881,7 +879,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             // should ensure that, unless this happens within a snapshot that's
             // rolled back, fulfillment or evaluation will notice the cycle.
 
-            infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+            if use_cache {
+                infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+            }
             return Err(InProgress);
         }
         Err(ProjectionCacheEntry::Recur) => {
@@ -963,20 +963,26 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                         .map_or(false, |res| res.must_apply_considering_regions())
             });
 
-            infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+            if use_cache {
+                infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+            }
             obligations.extend(result.obligations);
             Ok(Some(result.value))
         }
         Ok(ProjectedTy::NoProgress(projected_ty)) => {
             debug!(?projected_ty, "opt_normalize_projection_type: no progress");
             let result = Normalized { value: projected_ty, obligations: vec![] };
-            infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+            if use_cache {
+                infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+            }
             // No need to extend `obligations`.
             Ok(Some(result.value))
         }
         Err(ProjectionTyError::TooManyCandidates) => {
             debug!("opt_normalize_projection_type: too many candidates");
-            infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+            if use_cache {
+                infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+            }
             Ok(None)
         }
         Err(ProjectionTyError::TraitSelectionError(_)) => {
@@ -986,7 +992,9 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             // Trait`, which when processed will cause the error to be
             // reported later
 
-            infcx.inner.borrow_mut().projection_cache().error(cache_key);
+            if use_cache {
+                infcx.inner.borrow_mut().projection_cache().error(cache_key);
+            }
             let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
             obligations.extend(result.obligations);
             Ok(Some(result.value))
@@ -1477,7 +1485,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
             }
             super::ImplSource::AutoImpl(..)
             | super::ImplSource::Builtin(..)
-            | super::ImplSource::TraitUpcasting(_) => {
+            | super::ImplSource::TraitUpcasting(_)
+            | super::ImplSource::ConstDrop(_) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
@@ -1549,7 +1558,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
         | super::ImplSource::Param(..)
         | super::ImplSource::Builtin(..)
         | super::ImplSource::TraitUpcasting(_)
-        | super::ImplSource::TraitAlias(..) => {
+        | super::ImplSource::TraitAlias(..)
+        | super::ImplSource::ConstDrop(_) => {
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
index e18828fec3f6bf6aedaabb5ff8e5f605ae0ee007..6d64dc8254bb4a426379aa977ba7790e6000a16a 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_hir as hir;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::spec::abi::Abi;
 
 use crate::traits::coherence::Conflict;
@@ -277,6 +277,16 @@ pub(super) fn assemble_candidates<'o>(
             self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
         } else if lang_items.unsize_trait() == Some(def_id) {
             self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+        } else if lang_items.drop_trait() == Some(def_id)
+            && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
+        {
+            if self.is_in_const_context {
+                self.assemble_const_drop_candidates(obligation, &mut candidates)?;
+            } else {
+                debug!("passing ~const Drop bound; in non-const context");
+                // `~const Drop` when we are not in a const context has no effect.
+                candidates.vec.push(ConstDropCandidate)
+            }
         } else {
             if lang_items.clone_trait() == Some(def_id) {
                 // Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -803,4 +813,118 @@ fn assemble_builtin_bound_candidates(
             }
         }
     }
+
+    fn assemble_const_drop_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
+
+        while let Some((ty, depth)) = stack.pop() {
+            let mut noreturn = false;
+
+            self.check_recursion_depth(depth, obligation)?;
+            let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+            let mut copy_obligation =
+                obligation.with(obligation.predicate.rebind(ty::TraitPredicate {
+                    trait_ref: ty::TraitRef {
+                        def_id: self.tcx().require_lang_item(hir::LangItem::Copy, None),
+                        substs: self.tcx().mk_substs_trait(ty, &[]),
+                    },
+                    constness: ty::BoundConstness::NotConst,
+                }));
+            copy_obligation.recursion_depth = depth + 1;
+            self.assemble_candidates_from_impls(&copy_obligation, &mut copy_candidates);
+            let copy_conditions = self.copy_clone_conditions(&copy_obligation);
+            self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
+            if !copy_candidates.vec.is_empty() {
+                noreturn = true;
+            }
+            debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
+
+            match ty.kind() {
+                ty::Int(_)
+                | ty::Uint(_)
+                | ty::Float(_)
+                | ty::Infer(ty::IntVar(_))
+                | ty::Infer(ty::FloatVar(_))
+                | ty::FnPtr(_)
+                | ty::Never
+                | ty::Ref(..)
+                | ty::FnDef(..)
+                | ty::RawPtr(_)
+                | ty::Bool
+                | ty::Char
+                | ty::Str
+                | ty::Foreign(_) => {} // Do nothing. These types satisfy `const Drop`.
+
+                ty::Adt(def, subst) => {
+                    let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+                    self.assemble_candidates_from_impls(
+                        &obligation.with(obligation.predicate.map_bound(|mut pred| {
+                            pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]);
+                            pred
+                        })),
+                        &mut set,
+                    );
+                    stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
+
+                    debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt");
+                    if set.vec.into_iter().any(|candidate| {
+                        if let SelectionCandidate::ImplCandidate(did) = candidate {
+                            matches!(self.tcx().impl_constness(did), hir::Constness::NotConst)
+                        } else {
+                            false
+                        }
+                    }) {
+                        if !noreturn {
+                            // has non-const Drop
+                            return Ok(());
+                        }
+                        debug!("not returning");
+                    }
+                }
+
+                ty::Array(ty, _) => stack.push((ty, depth + 1)),
+
+                ty::Tuple(_) => stack.extend(ty.tuple_fields().map(|t| (t, depth + 1))),
+
+                ty::Closure(_, substs) => {
+                    stack.extend(substs.as_closure().upvar_tys().map(|t| (t, depth + 1)))
+                }
+
+                ty::Generator(_, substs, _) => {
+                    let substs = substs.as_generator();
+                    stack.extend(substs.upvar_tys().map(|t| (t, depth + 1)));
+                    stack.push((substs.witness(), depth + 1));
+                }
+
+                ty::GeneratorWitness(tys) => stack.extend(
+                    self.tcx().erase_late_bound_regions(*tys).iter().map(|t| (t, depth + 1)),
+                ),
+
+                ty::Slice(ty) => stack.push((ty, depth + 1)),
+
+                ty::Opaque(..)
+                | ty::Dynamic(..)
+                | ty::Error(_)
+                | ty::Bound(..)
+                | ty::Infer(_)
+                | ty::Placeholder(_)
+                | ty::Projection(..)
+                | ty::Param(..) => {
+                    if !noreturn {
+                        return Ok(());
+                    }
+                    debug!("not returning");
+                }
+            }
+            debug!(?stack, "assemble_const_drop_candidates - in loop");
+        }
+        // all types have passed.
+        candidates.vec.push(ConstDropCandidate);
+
+        Ok(())
+    }
 }
index 6fae8173985be82c233b0ce04dcac77e09b7e55c..3b6555de912e959465d14a13180ee4ed2ffdd9a7 100644 (file)
@@ -28,7 +28,7 @@
 use crate::traits::VtblSegment;
 use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
 use crate::traits::{
-    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
+    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData,
     ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
     ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
     ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
@@ -124,6 +124,8 @@ pub(super) fn confirm_candidate(
                 let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
                 Ok(ImplSource::TraitUpcasting(data))
             }
+
+            ConstDropCandidate => Ok(ImplSource::ConstDrop(ImplSourceConstDropData)),
         }
     }
 
index 22013fb79cf797d3f68dd9d49a02331ee5e8b331..50d6f82ae18fa0a6e9654aecdcebdbf1be3da4d3 100644 (file)
 use super::util::{closure_trait_ref_and_return_type, predicate_for_trait_def};
 use super::wf;
 use super::DerivedObligationCause;
+use super::Normalized;
 use super::Obligation;
 use super::ObligationCauseCode;
 use super::Selection;
 use super::SelectionResult;
 use super::TraitQueryMode;
-use super::{Normalized, ProjectionCacheKey};
 use super::{ObligationCause, PredicateObligation, TraitObligation};
 use super::{Overflow, SelectionError, Unimplemented};
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
 use crate::traits::error_reporting::InferCtxtExt;
-use crate::traits::project::ProjectionCacheKeyExt;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
@@ -34,8 +33,8 @@
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fast_reject;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
@@ -315,6 +314,10 @@ pub fn tcx(&self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
+    pub fn is_intercrate(&self) -> bool {
+        self.intercrate
+    }
+
     /// 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 {
@@ -574,14 +577,7 @@ fn evaluate_predicate_recursively<'o>(
                     match project::poly_project_and_unify_type(self, &project_obligation) {
                         Ok(Ok(Some(mut subobligations))) => {
                             self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
-                            let result = self
-                                .evaluate_predicates_recursively(previous_stack, subobligations);
-                            if let Some(key) =
-                                ProjectionCacheKey::from_poly_projection_predicate(self, data)
-                            {
-                                self.infcx.inner.borrow_mut().projection_cache().complete(key);
-                            }
-                            result
+                            self.evaluate_predicates_recursively(previous_stack, subobligations)
                         }
                         Ok(Ok(None)) => Ok(EvaluatedToAmbig),
                         Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur),
@@ -982,6 +978,14 @@ fn check_evaluation_cache(
         param_env: ty::ParamEnv<'tcx>,
         trait_ref: ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>,
     ) -> Option<EvaluationResult> {
+        // Neither the global nor local cache is aware of intercrate
+        // mode, so don't do any caching. In particular, we might
+        // re-use the same `InferCtxt` with both an intercrate
+        // and non-intercrate `SelectionContext`
+        if self.intercrate {
+            return None;
+        }
+
         let tcx = self.tcx();
         if self.can_use_global_caches(param_env) {
             if let Some(res) = tcx.evaluation_cache.get(&param_env.and(trait_ref), tcx) {
@@ -1004,6 +1008,14 @@ fn insert_evaluation_cache(
             return;
         }
 
+        // Neither the global nor local cache is aware of intercrate
+        // mode, so don't do any caching. In particular, we might
+        // re-use the same `InferCtxt` with both an intercrate
+        // and non-intercrate `SelectionContext`
+        if self.intercrate {
+            return;
+        }
+
         if self.can_use_global_caches(param_env) {
             if !trait_ref.needs_infer() {
                 debug!(?trait_ref, ?result, "insert_evaluation_cache global");
@@ -1038,19 +1050,15 @@ fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(
         it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
     }
 
-    /// Checks that the recursion limit has not been exceeded.
-    ///
-    /// The weird return type of this function allows it to be used with the `try` (`?`)
-    /// operator within certain functions.
-    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+    fn check_recursion_depth<T: Display + TypeFoldable<'tcx>>(
         &self,
-        obligation: &Obligation<'tcx, T>,
-        error_obligation: &Obligation<'tcx, V>,
+        depth: usize,
+        error_obligation: &Obligation<'tcx, T>,
     ) -> Result<(), OverflowError> {
-        if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
+        if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
             match self.query_mode {
                 TraitQueryMode::Standard => {
-                    self.infcx().report_overflow_error(error_obligation, true);
+                    self.infcx.report_overflow_error(error_obligation, true);
                 }
                 TraitQueryMode::Canonical => {
                     return Err(OverflowError);
@@ -1060,6 +1068,19 @@ fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFolda
         Ok(())
     }
 
+    /// Checks that the recursion limit has not been exceeded.
+    ///
+    /// The weird return type of this function allows it to be used with the `try` (`?`)
+    /// operator within certain functions.
+    #[inline(always)]
+    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        error_obligation: &Obligation<'tcx, V>,
+    ) -> Result<(), OverflowError> {
+        self.check_recursion_depth(obligation.recursion_depth, error_obligation)
+    }
+
     fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
     where
         OP: FnOnce(&mut Self) -> R,
@@ -1079,28 +1100,23 @@ fn filter_impls(
         let tcx = self.tcx();
         // Respect const trait obligations
         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);
-                    }
+            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 => {}
+                ConstDropCandidate => {}
+                _ => {
+                    // reject all other types of candidates
+                    return Err(Unimplemented);
                 }
             }
         }
@@ -1185,6 +1201,13 @@ fn check_candidate_cache(
         param_env: ty::ParamEnv<'tcx>,
         cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
+        // Neither the global nor local cache is aware of intercrate
+        // mode, so don't do any caching. In particular, we might
+        // re-use the same `InferCtxt` with both an intercrate
+        // and non-intercrate `SelectionContext`
+        if self.intercrate {
+            return None;
+        }
         let tcx = self.tcx();
         let pred = &cache_fresh_trait_pred.skip_binder();
         let trait_ref = pred.trait_ref;
@@ -1221,6 +1244,13 @@ fn can_cache_candidate(
         &self,
         result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
     ) -> bool {
+        // Neither the global nor local cache is aware of intercrate
+        // mode, so don't do any caching. In particular, we might
+        // re-use the same `InferCtxt` with both an intercrate
+        // and non-intercrate `SelectionContext`
+        if self.intercrate {
+            return false;
+        }
         match result {
             Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
             _ => true,
@@ -1476,21 +1506,24 @@ fn candidate_should_be_dropped_in_favor_of(
             (
                 BuiltinCandidate { has_nested: false }
                 | DiscriminantKindCandidate
-                | PointeeCandidate,
+                | PointeeCandidate
+                | ConstDropCandidate,
                 _,
             ) => true,
             (
                 _,
                 BuiltinCandidate { has_nested: false }
                 | DiscriminantKindCandidate
-                | PointeeCandidate,
+                | PointeeCandidate
+                | ConstDropCandidate,
             ) => false,
 
             (ParamCandidate(other), ParamCandidate(victim)) => {
-                let value_same_except_bound_vars = other.value.skip_binder()
+                let same_except_bound_vars = other.value.skip_binder()
                     == victim.value.skip_binder()
+                    && other.constness == victim.constness
                     && !other.value.skip_binder().has_escaping_bound_vars();
-                if value_same_except_bound_vars {
+                if same_except_bound_vars {
                     // See issue #84398. In short, we can generate multiple ParamCandidates which are
                     // the same except for unused bound vars. Just pick the one with the fewest bound vars
                     // or the current one if tied (they should both evaluate to the same answer). This is
@@ -2019,7 +2052,7 @@ fn match_impl(
         let cause = ObligationCause::new(
             obligation.cause.span,
             obligation.cause.body_id,
-            ObligationCauseCode::MatchImpl(Lrc::new(obligation.cause.code.clone()), impl_def_id),
+            ObligationCauseCode::MatchImpl(obligation.cause.clone(), impl_def_id),
         );
 
         let InferOk { obligations, .. } = self
@@ -2445,7 +2478,7 @@ fn get_provisional(
             "get_provisional = {:#?}",
             self.map.borrow().get(&fresh_trait_ref),
         );
-        Some(self.map.borrow().get(&fresh_trait_ref)?.clone())
+        Some(*self.map.borrow().get(&fresh_trait_ref)?)
     }
 
     /// Insert a provisional result into the cache. The result came
index c8bcab6efd7ca4cac621368a8e59036b8a0c799a..2ecc169e1cf1dd12bfed21810fdc1b5d5a18018b 100644 (file)
@@ -104,19 +104,21 @@ fn insert(
                 let self_ty = trait_ref.self_ty();
 
                 // FIXME: should postpone string formatting until we decide to actually emit.
-                with_no_trimmed_paths(|| OverlapError {
-                    with_impl: possible_sibling,
-                    trait_desc: trait_ref.print_only_trait_path().to_string(),
-                    // Only report the `Self` type if it has at least
-                    // some outer concrete shell; otherwise, it's
-                    // not adding much information.
-                    self_desc: if self_ty.has_concrete_skeleton() {
-                        Some(self_ty.to_string())
-                    } else {
-                        None
-                    },
-                    intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
-                    involves_placeholder: overlap.involves_placeholder,
+                with_no_trimmed_paths(|| {
+                    OverlapError {
+                        with_impl: possible_sibling,
+                        trait_desc: trait_ref.print_only_trait_path().to_string(),
+                        // Only report the `Self` type if it has at least
+                        // some outer concrete shell; otherwise, it's
+                        // not adding much information.
+                        self_desc: if self_ty.has_concrete_skeleton() {
+                            Some(self_ty.to_string())
+                        } else {
+                            None
+                        },
+                        intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
+                        involves_placeholder: overlap.involves_placeholder,
+                    }
                 })
             };
 
index 75307f135636be8f9be8f425e12f9a4b6c30207e..611ff26d652277ebfc3ef482faff31a4624af93f 100644 (file)
@@ -209,7 +209,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
         _ => return,
     };
     let fix_span =
-        |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind {
+        |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
             hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
             _ => impl_item_ref.span,
         };
index 219165ff5503555b46e09d3ffab19731e5ec91ef..2e56a1bf6839e708d1ee90917c6fb73cf78be1db 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_traits"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 tracing = "0.1"
index 2eb27fb1ad67e66c02800b8d342926c4c02c6dd5..78df95e680e005fd7fcc7c0d626f153b1dda6517 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_ty_utils"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 tracing = "0.1"
index b00d2ab35617f5d8986357ffe9c13d4a9ba545d9..87b729faa54e0ad5f34796d330d236b9270612e7 100644 (file)
@@ -386,7 +386,8 @@ fn resolve_associated_item<'tcx>(
         | traits::ImplSource::TraitAlias(..)
         | traits::ImplSource::DiscriminantKind(..)
         | traits::ImplSource::Pointee(..)
-        | traits::ImplSource::TraitUpcasting(_) => None,
+        | traits::ImplSource::TraitUpcasting(_)
+        | traits::ImplSource::ConstDrop(_) => None,
     })
 }
 
index d837af85d58ae912933b202a95a927b043026b97..32d271d94c8ea2ac79984c2fc5b7562237191e12 100644 (file)
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
 
 fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let adt_fields =
+    let adt_components =
         move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
+
     // If we don't know a type doesn't need drop, for example if it's a type
     // parameter without a `Copy` bound, then we conservatively return that it
     // needs drop.
-    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
+    let res =
+        NeedsDropTypes::new(tcx, query.param_env, query.value, adt_components).next().is_some();
+
     debug!("needs_drop_raw({:?}) = {:?}", query, res);
     res
 }
index 27ad7bf4c2d46eae363666ac330ed315791fcfb0..3d3b2743700917090e208f651426d5b3d5d3e79a 100644 (file)
@@ -100,7 +100,7 @@ fn associated_item_from_trait_item_ref(
 fn associated_item_from_impl_item_ref(
     tcx: TyCtxt<'_>,
     parent_def_id: LocalDefId,
-    impl_item_ref: &hir::ImplItemRef<'_>,
+    impl_item_ref: &hir::ImplItemRef,
 ) -> ty::AssocItem {
     let def_id = impl_item_ref.id.def_id;
     let (kind, has_self) = match impl_item_ref.kind {
index 1f6acbe0d811da4bb047434b205c4b17d9aca38a..439e6cdf70698945a183501613650e651a60454b 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_type_ir"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 doctest = false
index dd76a5e4b99b235b0ba395fa38e95776b3029f3e..7e570e151c5298c6431481097493273a823bdcbc 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_typeck"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 test = false
index 51bb09e4c54ba29bebcf1a8356bb01a9a6fc9587..33df541eb2ba88ccb19303722bf0193f7e04edca 100644 (file)
@@ -1687,14 +1687,13 @@ fn one_bound_for_assoc_type<I>(
                             constraint=constraint,
                         ));
                     } else {
-                        err.span_suggestion(
-                            span,
+                        err.span_suggestion_verbose(
+                            span.with_hi(assoc_name.span.lo()),
                             "use fully qualified syntax to disambiguate",
                             format!(
-                                "<{} as {}>::{}",
+                                "<{} as {}>::",
                                 ty_param_name(),
                                 bound.print_only_trait_path(),
-                                assoc_name,
                             ),
                             Applicability::MaybeIncorrect,
                         );
@@ -2418,13 +2417,14 @@ fn impl_trait_ty_to_ty(
         let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
             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] =>
-                    {
+                if let GenericParamDefKind::Lifetime = param.kind {
+                    if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
                         self.ast_region_to_region(lifetime, None).into()
+                    } else {
+                        bug!()
                     }
-                    _ => bug!(),
+                } else {
+                    bug!()
                 }
             } else {
                 match param.kind {
index d101551085976077688375471a3592fcfe0567f5..1cc06b8c2e544b9ca5bdf2130cd61ea1dd21b46f 100644 (file)
@@ -72,7 +72,16 @@ pub fn check_call(
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let original_callee_ty = self.check_expr(callee_expr);
+        let original_callee_ty = match &callee_expr.kind {
+            hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
+                .check_expr_with_expectation_and_args(
+                    callee_expr,
+                    Expectation::NoExpectation,
+                    arg_exprs,
+                ),
+            _ => self.check_expr(callee_expr),
+        };
+
         let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
 
         let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
index 14550690e63e01e542cfab488bb84b2f480d1679..4ea7a8694c075c7d52ea7955270bb9617cc06c87 100644 (file)
@@ -362,6 +362,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                                 ),
                                 self.cast_ty,
                                 AllowTwoPhase::No,
+                                None,
                             )
                             .is_ok()
                         {
@@ -379,6 +380,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                                     ),
                                     self.cast_ty,
                                     AllowTwoPhase::No,
+                                    None,
                                 )
                                 .is_ok()
                         {
@@ -394,6 +396,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                                 fcx.tcx.mk_ref(reg, TypeAndMut { ty: self.expr_ty, mutbl }),
                                 self.cast_ty,
                                 AllowTwoPhase::No,
+                                None,
                             )
                             .is_ok()
                     {
@@ -409,6 +412,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
                             ),
                             self.cast_ty,
                             AllowTwoPhase::No,
+                            None,
                         )
                         .is_ok()
                     {
@@ -666,6 +670,7 @@ pub fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
                             self.expr_ty,
                             fcx.tcx.mk_fn_ptr(f),
                             AllowTwoPhase::No,
+                            None,
                         );
                         if let Err(TypeError::IntrinsicCast) = res {
                             return Err(CastError::IllegalCast);
@@ -829,7 +834,7 @@ fn check_ref_cast(
 
                 // Coerce to a raw pointer so that we generate AddressOf in MIR.
                 let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
-                fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
+                fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
                     .unwrap_or_else(|_| {
                         bug!(
                         "could not cast from reference to array to pointer to array ({:?} to {:?})",
@@ -861,7 +866,7 @@ fn check_addr_ptr_cast(
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'_>> {
-        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No) {
+        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
             Ok(_) => Ok(()),
             Err(err) => Err(err),
         }
index 3c9d5b4def4e7a83a67655167919346a98b78eb7..d6c59312c0bc8d558ae68866b7299df470649eac 100644 (file)
@@ -214,7 +214,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
     } else {
         fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-        fcx.check_return_expr(&body.value);
+        fcx.check_return_expr(&body.value, false);
     }
     fcx.in_tail_expr = false;
 
@@ -688,7 +688,7 @@ fn check_opaque_meets_bounds<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, hir_id);
-        fcx.regionck_item(hir_id, span, &[]);
+        fcx.regionck_item(hir_id, span, FxHashSet::default());
     });
 }
 
@@ -906,7 +906,7 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
     full_impl_span: Span,
     impl_id: LocalDefId,
     impl_trait_ref: ty::TraitRef<'tcx>,
-    impl_item_refs: &[hir::ImplItemRef<'_>],
+    impl_item_refs: &[hir::ImplItemRef],
 ) {
     // If the trait reference itself is erroneous (so the compilation is going
     // to fail), skip checking the items here -- the `impl_item` table in `tcx`
index 3bfab9d513f375e6540a3f7471f3c3342d172485..92d0470bc2f58ceb92550ad72a12130192b8bb1b 100644 (file)
@@ -707,13 +707,7 @@ fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceRe
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    self.report_selection_error(
-                        obligation.clone(),
-                        &obligation,
-                        &err,
-                        false,
-                        false,
-                    );
+                    self.report_selection_error(obligation.clone(), &obligation, &err, false);
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
@@ -941,11 +935,13 @@ pub fn try_coerce(
         expr_ty: Ty<'tcx>,
         target: Ty<'tcx>,
         allow_two_phase: AllowTwoPhase,
+        cause: Option<ObligationCause<'tcx>>,
     ) -> RelateResult<'tcx, Ty<'tcx>> {
         let source = self.resolve_vars_with_obligations(expr_ty);
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
-        let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
+        let cause =
+            cause.unwrap_or_else(|| self.cause(expr.span, ObligationCauseCode::ExprAssignable));
         let coerce = Coerce::new(self, cause, allow_two_phase);
         let ok = self.commit_if_ok(|_| coerce.coerce(source, target))?;
 
@@ -1003,6 +999,12 @@ fn try_find_coercion_lub<E>(
             exprs.len()
         );
 
+        // The following check fixes #88097, where the compiler erroneously
+        // attempted to coerce a closure type to itself via a function pointer.
+        if prev_ty == new_ty {
+            return Ok(prev_ty);
+        }
+
         // Special-case that coercion alone cannot handle:
         // Function items or non-capturing closures of differing IDs or InternalSubsts.
         let (a_sig, b_sig) = {
@@ -1363,7 +1365,13 @@ pub fn coerce_forced_unit<'a>(
                 // Special-case the first expression we are coercing.
                 // To be honest, I'm not entirely sure why we do this.
                 // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
-                fcx.try_coerce(expression, expression_ty, self.expected_ty, AllowTwoPhase::No)
+                fcx.try_coerce(
+                    expression,
+                    expression_ty,
+                    self.expected_ty,
+                    AllowTwoPhase::No,
+                    Some(cause.clone()),
+                )
             } else {
                 match self.expressions {
                     Expressions::Dynamic(ref exprs) => fcx.try_find_coercion_lub(
index d59291b8fd493e1a1c2106e7c629585ac3ff167a..d5b631df058aef9c12428677dbfa52f7aec344d3 100644 (file)
@@ -1,4 +1,5 @@
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -250,7 +251,7 @@ fn compare_predicate_entailment<'tcx>(
         // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let mut wf_tys = vec![];
+        let mut wf_tys = FxHashSet::default();
 
         let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
@@ -398,7 +399,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, &wf_tys);
+        fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys);
 
         Ok(())
     })
@@ -1098,7 +1099,7 @@ fn compare_const_param_types<'tcx>(
         }
 
         let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
-        fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
+        fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default());
     });
 }
 
@@ -1216,7 +1217,7 @@ fn compare_type_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default());
 
         Ok(())
     })
@@ -1436,10 +1437,10 @@ pub fn check_type_bounds<'tcx>(
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
         let implied_bounds = match impl_ty.container {
-            ty::TraitContainer(_) => vec![],
+            ty::TraitContainer(_) => FxHashSet::default(),
             ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
         };
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds);
 
         Ok(())
     })
index 808685d7fa9c8885038f470c9792050b815ee6de..722b110ed61084f5b0454bba56be11566a59d719 100644 (file)
@@ -17,7 +17,6 @@
 
 use super::method::probe;
 
-use std::fmt;
 use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -135,7 +134,7 @@ pub fn demand_coerce_diag(
     ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
         let expected = self.resolve_vars_with_obligations(expected);
 
-        let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) {
+        let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
             Ok(ty) => return (ty, None),
             Err(e) => e,
         };
@@ -589,7 +588,8 @@ pub fn check_ref(
                     // E.g. for `&format!("")`, where we want the span to the
                     // `format!()` invocation instead of its expansion.
                     if let Some(call_span) =
-                        iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s))
+                        iter::successors(Some(expr.span), |s| s.parent_callsite())
+                            .find(|&s| sp.contains(s))
                     {
                         if sm.span_to_snippet(call_span).is_ok() {
                             return Some((
@@ -771,9 +771,10 @@ pub fn check_for_cast(
         // For now, don't suggest casting with `as`.
         let can_cast = false;
 
-        let prefix = if let Some(hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Struct(_, fields, _),
-            ..
+        let mut sugg = vec![];
+
+        if let Some(hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Struct(_, fields, _), ..
         })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
         {
             // `expr` is a literal field for a struct, only suggest if appropriate
@@ -782,12 +783,12 @@ pub fn check_for_cast(
                 .find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand)
             {
                 // This is a field literal
-                Some(field) => format!("{}: ", field.ident),
+                Some(field) => {
+                    sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
+                }
                 // Likely a field was meant, but this field wasn't found. Do not suggest anything.
                 None => return false,
             }
-        } else {
-            String::new()
         };
 
         if let hir::ExprKind::Call(path, args) = &expr.kind {
@@ -842,28 +843,38 @@ pub fn check_for_cast(
             checked_ty, expected_ty,
         );
 
-        let with_opt_paren: fn(&dyn fmt::Display) -> String =
-            if expr.precedence().order() < PREC_POSTFIX {
-                |s| format!("({})", s)
-            } else {
-                |s| s.to_string()
-            };
+        let close_paren = if expr.precedence().order() < PREC_POSTFIX {
+            sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
+            ")"
+        } else {
+            ""
+        };
 
-        let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty);
-        let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src));
-        let suffix_suggestion = with_opt_paren(&format_args!(
-            "{}{}",
+        let mut cast_suggestion = sugg.clone();
+        cast_suggestion
+            .push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty)));
+        let mut into_suggestion = sugg.clone();
+        into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren)));
+        let mut suffix_suggestion = sugg.clone();
+        suffix_suggestion.push((
             if matches!(
                 (&expected_ty.kind(), &checked_ty.kind()),
                 (ty::Int(_) | ty::Uint(_), ty::Float(_))
             ) {
                 // Remove fractional part from literal, for example `42.0f32` into `42`
                 let src = src.trim_end_matches(&checked_ty.to_string());
-                src.split('.').next().unwrap()
+                let len = src.split('.').next().unwrap().len();
+                expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
             } else {
-                src.trim_end_matches(&checked_ty.to_string())
+                let len = src.trim_end_matches(&checked_ty.to_string()).len();
+                expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
+            },
+            if expr.precedence().order() < PREC_POSTFIX {
+                // Readd `)`
+                format!("{})", expected_ty)
+            } else {
+                expected_ty.to_string()
             },
-            expected_ty,
         ));
         let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
             if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false }
@@ -890,22 +901,32 @@ pub fn check_for_cast(
                         .ok()
                         .map(|src| (expr, src))
                 });
-                let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
+                let (msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
                     (lhs_expr_and_src, exp_to_found_is_fallible)
                 {
                     let msg = format!(
                         "you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
                         lhs_src, expected_ty, checked_ty, src
                     );
-                    let suggestion = format!("{}::from({})", checked_ty, lhs_src);
-                    (lhs_expr.span, msg, suggestion)
+                    let suggestion = vec![
+                        (lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)),
+                        (lhs_expr.span.shrink_to_hi(), ")".to_string()),
+                    ];
+                    (msg, suggestion)
                 } else {
                     let msg = format!("{} and panic if the converted value doesn't fit", msg);
-                    let suggestion =
-                        format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
-                    (expr.span, msg, suggestion)
+                    let mut suggestion = sugg.clone();
+                    suggestion.push((
+                        expr.span.shrink_to_hi(),
+                        format!("{}.try_into().unwrap()", close_paren),
+                    ));
+                    (msg, suggestion)
                 };
-                err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable);
+                err.multipart_suggestion_verbose(
+                    &msg,
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
             };
 
         let suggest_to_change_suffix_or_into =
@@ -943,7 +964,7 @@ pub fn check_for_cast(
                 } else {
                     into_suggestion.clone()
                 };
-                err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable);
+                err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable);
             };
 
         match (&expected_ty.kind(), &checked_ty.kind()) {
@@ -997,16 +1018,14 @@ pub fn check_for_cast(
                 if found.bit_width() < exp.bit_width() {
                     suggest_to_change_suffix_or_into(err, false, true);
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else if can_cast {
                     // Missing try_into implementation for `f64` to `f32`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!("{}, producing the closest possible value", cast_msg),
                         cast_suggestion,
                         Applicability::MaybeIncorrect, // lossy conversion
@@ -1016,16 +1035,14 @@ pub fn check_for_cast(
             }
             (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => {
                 if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else if can_cast {
                     // Missing try_into implementation for `{float}` to `{integer}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!("{}, rounding the float towards zero", msg),
                         cast_suggestion,
                         Applicability::MaybeIncorrect, // lossy conversion
@@ -1036,8 +1053,7 @@ pub fn check_for_cast(
             (&ty::Float(ref exp), &ty::Uint(ref found)) => {
                 // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer",
                             msg,
@@ -1046,16 +1062,14 @@ pub fn check_for_cast(
                         Applicability::MachineApplicable,
                     );
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else {
                     // Missing try_into implementation for `{integer}` to `{float}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer,
                                  rounded if necessary",
@@ -1070,8 +1084,7 @@ pub fn check_for_cast(
             (&ty::Float(ref exp), &ty::Int(ref found)) => {
                 // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer",
                             &msg,
@@ -1080,16 +1093,14 @@ pub fn check_for_cast(
                         Applicability::MachineApplicable,
                     );
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else {
                     // Missing try_into implementation for `{integer}` to `{float}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer, \
                                 rounded if necessary",
index d578fac4cdb227d0ed1ce86dc250d1cb24a18969..11b6c93a115283c8af05c75db1252ee916d427e0 100644 (file)
@@ -161,6 +161,17 @@ pub(super) fn check_expr_with_expectation(
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
+    ) -> Ty<'tcx> {
+        self.check_expr_with_expectation_and_args(expr, expected, &[])
+    }
+
+    /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
+    /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
+    pub(super) fn check_expr_with_expectation_and_args(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        expected: Expectation<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> Ty<'tcx> {
         if self.tcx().sess.verbose() {
             // make this code only run with -Zverbose because it is probably slow
@@ -198,7 +209,12 @@ pub(super) fn check_expr_with_expectation(
         let old_diverges = self.diverges.replace(Diverges::Maybe);
         let old_has_errors = self.has_errors.replace(false);
 
-        let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected));
+        let ty = ensure_sufficient_stack(|| match &expr.kind {
+            hir::ExprKind::Path(
+                qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..),
+            ) => self.check_expr_path(qpath, expr, args),
+            _ => self.check_expr_kind(expr, expected),
+        });
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
@@ -261,7 +277,7 @@ fn check_expr_kind(
             ExprKind::Path(QPath::LangItem(lang_item, _)) => {
                 self.check_lang_item_path(lang_item, expr)
             }
-            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr),
+            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
             ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
             ExprKind::LlvmInlineAsm(asm) => {
                 for expr in asm.outputs_exprs.iter().chain(asm.inputs_exprs.iter()) {
@@ -481,10 +497,11 @@ fn check_lang_item_path(
         self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
     }
 
-    fn check_expr_path(
+    pub(crate) fn check_expr_path(
         &self,
         qpath: &'tcx hir::QPath<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
@@ -517,16 +534,17 @@ fn check_expr_path(
                     // We just want to check sizedness, so instead of introducing
                     // placeholder lifetimes with probing, we just replace higher lifetimes
                     // with fresh vars.
+                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
                     let input = self
                         .replace_bound_vars_with_fresh_vars(
-                            expr.span,
+                            span,
                             infer::LateBoundRegionConversionTime::FnCall,
                             fn_sig.input(i),
                         )
                         .0;
                     self.require_type_is_sized_deferred(
                         input,
-                        expr.span,
+                        span,
                         traits::SizedArgumentType(None),
                     );
                 }
@@ -747,7 +765,7 @@ fn check_expr_return(
             if self.ret_coercion_span.get().is_none() {
                 self.ret_coercion_span.set(Some(e.span));
             }
-            self.check_return_expr(e);
+            self.check_return_expr(e, true);
         } else {
             let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
             if self.ret_coercion_span.get().is_none() {
@@ -776,16 +794,32 @@ fn check_expr_return(
         self.tcx.types.never
     }
 
-    pub(super) fn check_return_expr(&self, return_expr: &'tcx hir::Expr<'tcx>) {
+    /// `explicit_return` is `true` if we're checkng an explicit `return expr`,
+    /// and `false` if we're checking a trailing expression.
+    pub(super) fn check_return_expr(
+        &self,
+        return_expr: &'tcx hir::Expr<'tcx>,
+        explicit_return: bool,
+    ) {
         let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
             span_bug!(return_expr.span, "check_return_expr called outside fn body")
         });
 
         let ret_ty = ret_coercion.borrow().expected_ty();
         let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
+        let mut span = return_expr.span;
+        // Use the span of the trailing expression for our cause,
+        // not the span of the entire function
+        if !explicit_return {
+            if let ExprKind::Block(body, _) = return_expr.kind {
+                if let Some(last_expr) = body.expr {
+                    span = last_expr.span;
+                }
+            }
+        }
         ret_coercion.borrow_mut().coerce(
             self,
-            &self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
+            &self.cause(span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),
             return_expr,
             return_expr_ty,
         );
@@ -1826,6 +1860,7 @@ fn ban_private_field_access(
                 field,
                 expr_t,
                 expr,
+                None,
             );
         }
         err.emit();
@@ -1842,13 +1877,43 @@ fn ban_take_value_of_method(&self, expr: &hir::Expr<'_>, expr_t: Ty<'tcx>, field
             expr_t
         );
         err.span_label(field.span, "method, not a field");
-        if !self.expr_in_place(expr.hir_id) {
+        let expr_is_call =
+            if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
+                self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
+            {
+                expr.hir_id == callee.hir_id
+            } else {
+                false
+            };
+        let expr_snippet =
+            self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new());
+        let is_wrapped = expr_snippet.starts_with("(") && expr_snippet.ends_with(")");
+        let after_open = expr.span.lo() + rustc_span::BytePos(1);
+        let before_close = expr.span.hi() - rustc_span::BytePos(1);
+
+        if expr_is_call && is_wrapped {
+            err.multipart_suggestion(
+                "remove wrapping parentheses to call the method",
+                vec![
+                    (expr.span.with_hi(after_open), String::new()),
+                    (expr.span.with_lo(before_close), String::new()),
+                ],
+                Applicability::MachineApplicable,
+            );
+        } else if !self.expr_in_place(expr.hir_id) {
+            // Suggest call parentheses inside the wrapping parentheses
+            let span = if is_wrapped {
+                expr.span.with_lo(after_open).with_hi(before_close)
+            } else {
+                expr.span
+            };
             self.suggest_method_call(
                 &mut err,
                 "use parentheses to call the method",
                 field,
                 expr_t,
                 expr,
+                Some(span),
             );
         } else {
             err.help("methods are immutable and cannot be assigned to");
index 9748c0835bf12e29c4e6463208899f8f4cfe2fd9..ed01dae59f6723e1460d2a534c8c34faac305813 100644 (file)
@@ -83,7 +83,15 @@ pub(in super::super) fn warn_if_unreachable(&self, id: hir::HirId, span: Span, k
     /// version (resolve_vars_if_possible), this version will
     /// also select obligations if it seems useful, in an effort
     /// to get more type information.
-    pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+    pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
+    }
+
+    pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
+        &self,
+        mut ty: Ty<'tcx>,
+        mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
+    ) -> Ty<'tcx> {
         debug!("resolve_vars_with_obligations(ty={:?})", ty);
 
         // No Infer()? Nothing needs doing.
@@ -103,7 +111,7 @@ pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible(false, |_| {});
+        self.select_obligations_where_possible(false, mutate_fulfillment_errors);
         ty = self.resolve_vars_if_possible(ty);
 
         debug!("resolve_vars_with_obligations: ty={:?}", ty);
index 9efb52a08b7e10eb98daaab1dd43f2bebf7b5987..551522334aa00a7d9d328bdeb7a361c0f0e36854 100644 (file)
@@ -9,6 +9,7 @@
 };
 
 use rustc_ast as ast;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -324,6 +325,7 @@ pub(in super::super) fn check_argument_types(
                     self.point_at_arg_instead_of_call_if_possible(
                         errors,
                         &final_arg_types[..],
+                        expr,
                         sp,
                         &args,
                     );
@@ -354,8 +356,8 @@ pub(in super::super) fn check_argument_types(
                     continue;
                 }
 
-                debug!("checking the argument");
                 let formal_ty = formal_tys[i];
+                debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
 
                 // The special-cased logic below has three functions:
                 // 1. Provide as good of an expected type as possible.
@@ -367,6 +369,42 @@ pub(in super::super) fn check_argument_types(
                 //    to, which is `expected_ty` if `rvalue_hint` returns an
                 //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
                 let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
+
+                // Cause selection errors caused by resolving a single argument to point at the
+                // argument and not the call. This is otherwise redundant with the `demand_coerce`
+                // call immediately after, but it lets us customize the span pointed to in the
+                // fulfillment error to be more accurate.
+                let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
+                    coerce_ty,
+                    |errors| {
+                        // This is not coming from a macro or a `derive`.
+                        if sp.desugaring_kind().is_none()
+                        && !arg.span.from_expansion()
+                        // Do not change the spans of `async fn`s.
+                        && !matches!(
+                            expr.kind,
+                            hir::ExprKind::Call(
+                                hir::Expr {
+                                    kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
+                                    ..
+                                },
+                                _
+                            )
+                        ) {
+                            for error in errors {
+                                error.obligation.cause.make_mut().span = arg.span;
+                                let code = error.obligation.cause.code.clone();
+                                error.obligation.cause.make_mut().code =
+                                    ObligationCauseCode::FunctionArgumentObligation {
+                                        arg_hir_id: arg.hir_id,
+                                        call_hir_id: expr.hir_id,
+                                        parent_code: Lrc::new(code),
+                                    };
+                            }
+                        }
+                    },
+                );
+
                 // We're processing function arguments so we definitely want to use
                 // two-phase borrows.
                 self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
@@ -494,15 +532,25 @@ pub fn check_struct_path(
 
             Some((variant, ty))
         } else {
-            struct_span_err!(
-                self.tcx.sess,
-                path_span,
-                E0071,
-                "expected struct, variant or union type, found {}",
-                ty.sort_string(self.tcx)
-            )
-            .span_label(path_span, "not a struct")
-            .emit();
+            match ty.kind() {
+                ty::Error(_) => {
+                    // E0071 might be caused by a spelling error, which will have
+                    // already caused an error message and probably a suggestion
+                    // elsewhere. Refrain from emitting more unhelpful errors here
+                    // (issue #88844).
+                }
+                _ => {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        path_span,
+                        E0071,
+                        "expected struct, variant or union type, found {}",
+                        ty.sort_string(self.tcx)
+                    )
+                    .span_label(path_span, "not a struct")
+                    .emit();
+                }
+            }
             None
         }
     }
@@ -907,6 +955,7 @@ fn point_at_arg_instead_of_call_if_possible(
         &self,
         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
         final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)],
+        expr: &'tcx hir::Expr<'tcx>,
         call_sp: Span,
         args: &'tcx [hir::Expr<'tcx>],
     ) {
@@ -956,7 +1005,13 @@ fn point_at_arg_instead_of_call_if_possible(
                     // We make sure that only *one* argument matches the obligation failure
                     // and we assign the obligation's span to its expression's.
                     error.obligation.cause.make_mut().span = args[ref_in].span;
-                    error.points_at_arg_span = true;
+                    let code = error.obligation.cause.code.clone();
+                    error.obligation.cause.make_mut().code =
+                        ObligationCauseCode::FunctionArgumentObligation {
+                            arg_hir_id: args[ref_in].hir_id,
+                            call_hir_id: expr.hir_id,
+                            parent_code: Lrc::new(code),
+                        };
                 }
             }
         }
index 664954b0eb7a229673d8ad715b1545689f8a48b3..ff7a26853b1885c273d22baeeb8d36b9514ff7ed 100644 (file)
@@ -2,7 +2,7 @@
 //! intrinsics that the compiler exposes.
 
 use crate::errors::{
-    SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
+    UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
     WrongNumberOfGenericArgumentsToIntrinsic,
 };
 use crate::require_same_types;
@@ -468,6 +468,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         | sym::simd_reduce_max
         | sym::simd_reduce_min_nanless
         | sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
+        sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
         name if name.as_str().starts_with("simd_shuffle") => {
             match name.as_str()["simd_shuffle".len()..].parse() {
                 Ok(n) => {
@@ -475,7 +476,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
                     (2, params, param(1))
                 }
                 Err(_) => {
-                    tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name });
+                    let msg =
+                        format!("unrecognized platform-specific intrinsic function: `{}`", name);
+                    tcx.sess.struct_span_err(it.span, &msg).emit();
                     return;
                 }
             }
index 2136d925423b912df2543b47aab578bd8de45022..8e09aa97dcf345ea396f06fbbd7002576455d9a8 100644 (file)
@@ -141,6 +141,7 @@ pub fn method_exists(
         method_name: Ident,
         self_ty: Ty<'tcx>,
         call_expr: &hir::Expr<'_>,
+        span: Option<Span>,
     ) {
         let params = self
             .probe_for_name(
@@ -159,7 +160,7 @@ pub fn method_exists(
             .unwrap_or(0);
 
         // Account for `foo.bar<T>`;
-        let sugg_span = call_expr.span.shrink_to_hi();
+        let sugg_span = span.unwrap_or_else(|| call_expr.span).shrink_to_hi();
         let (suggestion, applicability) = (
             format!("({})", (0..params).map(|_| "_").collect::<Vec<_>>().join(", ")),
             if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect },
index 1c7d68a3d57d4325120a0586c07af81d385d9a64..cbfdce96bc57bdd0b1554f8b4e32ec1e8343faf6 100644 (file)
@@ -186,7 +186,7 @@ pub enum AutorefOrPtrAdjustment<'tcx> {
 impl<'tcx> AutorefOrPtrAdjustment<'tcx> {
     fn get_unsize(&self) -> Option<Ty<'tcx>> {
         match self {
-            AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => unsize.clone(),
+            AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
             AutorefOrPtrAdjustment::ToConstPtr => None,
         }
     }
index a746ad7ad4bc722b63c1d05287547301a87c87a6..9744f4f6483c75f8fcaf72f9db79c36cbf204219 100644 (file)
@@ -1655,7 +1655,7 @@ fn handle_external_res(
         tcx: TyCtxt<'_>,
         traits: &mut Vec<DefId>,
         external_mods: &mut FxHashSet<DefId>,
-        res: Res,
+        res: Res<!>,
     ) {
         match res {
             Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
index 803c440bbc98b3ae6f06aed391238390d38ea9df..a10490a9a15c7b75a4db20790d62c4bad5e0f394 100644 (file)
@@ -388,7 +388,7 @@ fn typeck_with_fallback<'tcx>(
             // 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![];
+            let mut wf_tys = FxHashSet::default();
             // 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());
@@ -451,7 +451,7 @@ fn typeck_with_fallback<'tcx>(
 
             fcx.write_ty(id, expected_type);
 
-            (fcx, vec![])
+            (fcx, FxHashSet::default())
         };
 
         let fallback_has_occurred = fcx.type_inference_fallback();
@@ -475,7 +475,7 @@ fn typeck_with_fallback<'tcx>(
         fcx.select_all_obligations_or_error();
 
         if fn_sig.is_some() {
-            fcx.regionck_fn(id, body, span, &wf_tys);
+            fcx.regionck_fn(id, body, span, wf_tys);
         } else {
             fcx.regionck_expr(body);
         }
index 9b495fba1975d01824abb7bb3095de2458d9c289..a574a63d63b28eb259c194969494cac59fbda510 100644 (file)
@@ -680,42 +680,53 @@ pub fn check_user_unop(
                         ex.span,
                         format!("cannot apply unary operator `{}`", op.as_str()),
                     );
-                    match actual.kind() {
-                        Uint(_) if op == hir::UnOp::Neg => {
-                            err.note("unsigned values cannot be negated");
-
-                            if let hir::ExprKind::Unary(
-                                _,
-                                hir::Expr {
-                                    kind:
-                                        hir::ExprKind::Lit(Spanned {
-                                            node: ast::LitKind::Int(1, _),
-                                            ..
-                                        }),
-                                    ..
-                                },
-                            ) = ex.kind
-                            {
-                                err.span_suggestion(
-                                    ex.span,
-                                    &format!(
-                                        "you may have meant the maximum value of `{}`",
-                                        actual
-                                    ),
-                                    format!("{}::MAX", actual),
-                                    Applicability::MaybeIncorrect,
-                                );
+
+                    let sp = self.tcx.sess.source_map().start_point(ex.span);
+                    if let Some(sp) =
+                        self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
+                    {
+                        // If the previous expression was a block expression, suggest parentheses
+                        // (turning this into a binary subtraction operation instead.)
+                        // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
+                        self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+                    } else {
+                        match actual.kind() {
+                            Uint(_) if op == hir::UnOp::Neg => {
+                                err.note("unsigned values cannot be negated");
+
+                                if let hir::ExprKind::Unary(
+                                    _,
+                                    hir::Expr {
+                                        kind:
+                                            hir::ExprKind::Lit(Spanned {
+                                                node: ast::LitKind::Int(1, _),
+                                                ..
+                                            }),
+                                        ..
+                                    },
+                                ) = ex.kind
+                                {
+                                    err.span_suggestion(
+                                        ex.span,
+                                        &format!(
+                                            "you may have meant the maximum value of `{}`",
+                                            actual
+                                        ),
+                                        format!("{}::MAX", actual),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            }
+                            Str | Never | Char | Tuple(_) | Array(_, _) => {}
+                            Ref(_, ref lty, _) if *lty.kind() == Str => {}
+                            _ => {
+                                let missing_trait = match op {
+                                    hir::UnOp::Neg => "std::ops::Neg",
+                                    hir::UnOp::Not => "std::ops::Not",
+                                    hir::UnOp::Deref => "std::ops::UnDerf",
+                                };
+                                suggest_impl_missing(&mut err, operand_ty, &missing_trait);
                             }
-                        }
-                        Str | Never | Char | Tuple(_) | Array(_, _) => {}
-                        Ref(_, ref lty, _) if *lty.kind() == Str => {}
-                        _ => {
-                            let missing_trait = match op {
-                                hir::UnOp::Neg => "std::ops::Neg",
-                                hir::UnOp::Not => "std::ops::Not",
-                                hir::UnOp::Deref => "std::ops::UnDerf",
-                            };
-                            suggest_impl_missing(&mut err, operand_ty, &missing_trait);
                         }
                     }
                     err.emit();
index 140a9d1126d32a29289207c7f7df4bc3884943c8..829268e3cb527d7b5240a75c4cd454f5b9a95327 100644 (file)
@@ -11,6 +11,7 @@
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::subst::GenericArg;
 use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
@@ -1261,7 +1262,8 @@ fn check_struct_pat_fields(
         };
 
         // Require `..` if struct has non_exhaustive attribute.
-        if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
+        let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+        if non_exhaustive && !etc {
             self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
         }
 
@@ -1276,7 +1278,7 @@ fn check_struct_pat_fields(
             if etc {
                 tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
             }
-        } else if !etc && !unmentioned_fields.is_empty() {
+        } else if !unmentioned_fields.is_empty() {
             let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
                 .iter()
                 .copied()
@@ -1284,16 +1286,19 @@ fn check_struct_pat_fields(
                     field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
                 })
                 .collect();
-
-            if accessible_unmentioned_fields.is_empty() {
-                unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
-            } else {
-                unmentioned_err = Some(self.error_unmentioned_fields(
-                    pat,
-                    &accessible_unmentioned_fields,
-                    accessible_unmentioned_fields.len() != unmentioned_fields.len(),
-                    &fields,
-                ));
+            if non_exhaustive {
+                self.non_exhaustive_reachable_pattern(pat, &accessible_unmentioned_fields, adt_ty)
+            } else if !etc {
+                if accessible_unmentioned_fields.is_empty() {
+                    unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
+                } else {
+                    unmentioned_err = Some(self.error_unmentioned_fields(
+                        pat,
+                        &accessible_unmentioned_fields,
+                        accessible_unmentioned_fields.len() != unmentioned_fields.len(),
+                        &fields,
+                    ));
+                }
             }
         }
         match (inexistent_fields_err, unmentioned_err) {
@@ -1447,7 +1452,8 @@ fn error_inexistent_fields(
                     plural
                 ),
             );
-            if plural == "" {
+
+            if unmentioned_fields.len() == 1 {
                 let input =
                     unmentioned_fields.iter().map(|(_, field)| field.name).collect::<Vec<_>>();
                 let suggested_name = find_best_match_for_name(&input, ident.name, None);
@@ -1468,6 +1474,18 @@ fn error_inexistent_fields(
                         // We don't want to throw `E0027` in case we have thrown `E0026` for them.
                         unmentioned_fields.retain(|&(_, x)| x.name != suggested_name);
                     }
+                } else if inexistent_fields.len() == 1 {
+                    let unmentioned_field = unmentioned_fields[0].1.name;
+                    err.span_suggestion_short(
+                        ident.span,
+                        &format!(
+                            "`{}` has a field named `{}`",
+                            tcx.def_path_str(variant.def_id),
+                            unmentioned_field
+                        ),
+                        unmentioned_field.to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
         }
@@ -1604,6 +1622,51 @@ fn error_no_accessible_fields(
         err
     }
 
+    /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns`
+    /// is not exhaustive enough.
+    ///
+    /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
+    fn non_exhaustive_reachable_pattern(
+        &self,
+        pat: &Pat<'_>,
+        unmentioned_fields: &[(&ty::FieldDef, Ident)],
+        ty: Ty<'tcx>,
+    ) {
+        fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
+            const LIMIT: usize = 3;
+            match witnesses {
+                [] => bug!(),
+                [witness] => format!("`{}`", witness),
+                [head @ .., tail] if head.len() < LIMIT => {
+                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+                    format!("`{}` and `{}`", head.join("`, `"), tail)
+                }
+                _ => {
+                    let (head, tail) = witnesses.split_at(LIMIT);
+                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+                    format!("`{}` and {} more", head.join("`, `"), tail.len())
+                }
+            }
+        }
+        let joined_patterns = joined_uncovered_patterns(
+            &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
+        );
+
+        self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
+        let mut lint = build.build("some fields are not explicitly listed");
+        lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
+
+        lint.help(
+            "ensure that all fields are mentioned explicitly by adding the suggested fields",
+        );
+        lint.note(&format!(
+            "the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+            ty,
+        ));
+        lint.emit();
+    });
+    }
+
     /// Returns a diagnostic reporting a struct pattern which does not mention some fields.
     ///
     /// ```text
index 290fa5fc36719278954ab0e9963399234d2d9ff3..134604a0e32b41ffea5e291c32ac60097f9011da 100644 (file)
@@ -76,6 +76,7 @@
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -126,7 +127,7 @@ pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) {
 
     /// Region checking during the WF phase for items. `wf_tys` are the
     /// types from which we should derive implied bounds, if any.
-    pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
+    pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) {
         debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
         let subject = self.tcx.hir().local_def_id(item_id);
         let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
@@ -149,7 +150,7 @@ pub(crate) fn regionck_fn(
         fn_id: hir::HirId,
         body: &'tcx hir::Body<'tcx>,
         span: Span,
-        wf_tys: &[Ty<'tcx>],
+        wf_tys: FxHashSet<Ty<'tcx>>,
     ) {
         debug!("regionck_fn(id={})", fn_id);
         let subject = self.tcx.hir().body_owner_def_id(body.id());
@@ -286,15 +287,10 @@ fn visit_fn_body(
         // because it will have no effect.
         //
         // FIXME(#27579) return types should not be implied bounds
-        let fn_sig_tys: Vec<_> =
+        let fn_sig_tys: FxHashSet<_> =
             fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
 
-        self.outlives_environment.add_implied_bounds(
-            self.fcx,
-            &fn_sig_tys[..],
-            body_id.hir_id,
-            span,
-        );
+        self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span);
         self.outlives_environment.save_implied_bounds(body_id.hir_id);
         self.link_fn_params(&body.params);
         self.visit_body(body);
index 17716afe3208fee68882fa83bdeb4d45cd6e6730..cb07fcf5fef5813fba8341be925567b9d55df4cc 100644 (file)
@@ -44,7 +44,7 @@ struct CheckWfFcxBuilder<'tcx> {
 impl<'tcx> CheckWfFcxBuilder<'tcx> {
     fn with_fcx<F>(&mut self, f: F)
     where
-        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec<Ty<'tcx>>,
+        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet<Ty<'tcx>>,
     {
         let id = self.id;
         let span = self.span;
@@ -59,7 +59,7 @@ fn with_fcx<F>(&mut self, f: F)
             }
             let wf_tys = f(&fcx);
             fcx.select_all_obligations_or_error();
-            fcx.regionck_item(id, span, &wf_tys);
+            fcx.regionck_item(id, span, wf_tys);
         });
     }
 }
@@ -394,7 +394,7 @@ fn check_associated_item(
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
         let (mut implied_bounds, self_ty) = match item.container {
-            ty::TraitContainer(_) => (vec![], fcx.tcx.types.self_param),
+            ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param),
             ty::ImplContainer(def_id) => {
                 (fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id))
             }
@@ -553,7 +553,7 @@ fn check_type_defn<'tcx, F>(
         check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
         // No implied bounds in a struct definition.
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -579,7 +579,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     for_item(tcx, item).with_fcx(|fcx| {
         check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -620,7 +620,7 @@ fn check_item_fn(
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let def_id = tcx.hir().local_def_id(item_id);
         let sig = tcx.fn_sig(def_id);
-        let mut implied_bounds = vec![];
+        let mut implied_bounds = FxHashSet::default();
         check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
         implied_bounds
     })
@@ -659,7 +659,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         }
 
         // No implied bounds in a const, etc.
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -918,14 +918,14 @@ fn check_fn_or_method<'fcx, 'tcx>(
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
     def_id: DefId,
-    implied_bounds: &mut Vec<Ty<'tcx>>,
+    implied_bounds: &mut FxHashSet<Ty<'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());
+    implied_bounds.insert(sig.output());
 
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
@@ -977,7 +977,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
     );
 
     // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.push(sig.output());
+    implied_bounds.insert(sig.output());
 
     debug!(?implied_bounds);
 
@@ -1513,7 +1513,11 @@ fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
             .collect()
     }
 
-    pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
+    pub(super) fn impl_implied_bounds(
+        &self,
+        impl_def_id: DefId,
+        span: Span,
+    ) -> FxHashSet<Ty<'tcx>> {
         match self.tcx.impl_trait_ref(impl_def_id) {
             Some(trait_ref) => {
                 // Trait impl: take implied bounds from all types that
@@ -1526,7 +1530,7 @@ pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<
                 // Inherent impl: take implied bounds from the `self` type.
                 let self_ty = self.tcx.type_of(impl_def_id);
                 let self_ty = self.normalize_associated_types_in(span, self_ty);
-                vec![self_ty]
+                std::array::IntoIter::new([self_ty]).collect()
             }
         }
     }
index c7be9e2123512cae236c673adf01cec411436b32..f3fe09ac0033d4802b8d1797d40fb91c57b343b2 100644 (file)
@@ -401,7 +401,7 @@ fn check_primitive_impl(
         lang: &str,
         ty: &str,
         span: Span,
-        assoc_items: &[hir::ImplItemRef<'_>],
+        assoc_items: &[hir::ImplItemRef],
     ) {
         match (lang_def_id, lang_def_id2) {
             (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
index 3688fa05e038eb2948da4152ded88e55e01aabd5..1bc7bc3e063d4be1c14c299c0355cc2182feb201 100644 (file)
@@ -46,7 +46,7 @@
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::{abi, PanicStrategy, SanitizerSet};
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use std::iter;
 
@@ -450,9 +450,9 @@ fn projected_ty_from_poly_trait_ref(
                             let suggestions = vec![
                                 (lt_sp, sugg),
                                 (
-                                    span,
+                                    span.with_hi(item_segment.ident.span.lo()),
                                     format!(
-                                        "{}::{}",
+                                        "{}::",
                                         // Replace the existing lifetimes with a new named lifetime.
                                         self.tcx
                                             .replace_late_bound_regions(poly_trait_ref, |_| {
@@ -465,7 +465,6 @@ fn projected_ty_from_poly_trait_ref(
                                                 ))
                                             })
                                             .0,
-                                        item_segment.ident
                                     ),
                                 ),
                             ];
@@ -487,14 +486,13 @@ fn projected_ty_from_poly_trait_ref(
                 | hir::Node::ForeignItem(_)
                 | hir::Node::TraitItem(_)
                 | hir::Node::ImplItem(_) => {
-                    err.span_suggestion(
-                        span,
+                    err.span_suggestion_verbose(
+                        span.with_hi(item_segment.ident.span.lo()),
                         "use a fully qualified path with inferred lifetimes",
                         format!(
-                            "{}::{}",
+                            "{}::",
                             // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
                             self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
-                            item_segment.ident
                         ),
                         Applicability::MaybeIncorrect,
                     );
@@ -2683,6 +2681,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
+    // With -Z panic-in-drop=abort, drop_in_place never unwinds.
+    if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
+        if Some(id) == tcx.lang_items().drop_in_place_fn() {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        }
+    }
+
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
index 1e6a240b2f86d857ce8761f7421775eca0287837..47077779616c012ae8a257213c829a37136e3390 100644 (file)
@@ -121,14 +121,6 @@ pub struct AssocTypeBindingNotAllowed {
     pub span: Span,
 }
 
-#[derive(SessionDiagnostic)]
-#[error = "E0439"]
-pub struct SimdShuffleMissingLength {
-    #[message = "invalid `simd_shuffle`, needs length: `{name}`"]
-    pub span: Span,
-    pub name: Symbol,
-}
-
 #[derive(SessionDiagnostic)]
 #[error = "E0436"]
 pub struct FunctionalRecordUpdateOnNonStruct {
index 194c4efdbb05888fb8b677e1361f06e22f0b0d7b..5d2f8fc4242756b798c1c9485cf999603f78fce3 100644 (file)
@@ -58,9 +58,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) {
     // We will tag this as part of the WF check -- logically, it is,
     // but it's one that we must perform earlier than the rest of
     // WfCheck.
-    for &module in tcx.hir().krate().modules.keys() {
-        tcx.ensure().check_mod_impl_wf(module);
-    }
+    tcx.hir().for_each_module(|module| tcx.ensure().check_mod_impl_wf(module))
 }
 
 fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
@@ -99,7 +97,7 @@ fn visit_foreign_item(&mut self, _foreign_item: &'tcx hir::ForeignItem<'tcx>) {}
 fn enforce_impl_params_are_constrained(
     tcx: TyCtxt<'_>,
     impl_def_id: LocalDefId,
-    impl_item_refs: &[hir::ImplItemRef<'_>],
+    impl_item_refs: &[hir::ImplItemRef],
 ) {
     // Every lifetime used in an associated type must be constrained.
     let impl_self_ty = tcx.type_of(impl_def_id);
@@ -230,7 +228,7 @@ impl trait, self type, or predicates",
 }
 
 /// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef<'_>]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
     let mut seen_type_items = FxHashMap::default();
     let mut seen_value_items = FxHashMap::default();
     for impl_item_ref in impl_item_refs {
index c703ca96ada6f7d1f728a736b65354cd86628508..f8714cdc70c19f7fcb3b547b068b6fcc5a1c37ae 100644 (file)
@@ -473,9 +473,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
     // FIXME(matthewjasper) We shouldn't need to use `track_errors`.
     tcx.sess.track_errors(|| {
         tcx.sess.time("type_collecting", || {
-            for &module in tcx.hir().krate().modules.keys() {
-                tcx.ensure().collect_mod_item_types(module);
-            }
+            tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
         });
     })?;
 
@@ -505,9 +503,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> {
 
     // NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
     tcx.sess.time("item_types_checking", || {
-        for &module in tcx.hir().krate().modules.keys() {
-            tcx.ensure().check_mod_item_types(module);
-        }
+        tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
     });
 
     tcx.sess.time("item_bodies_checking", || tcx.typeck_item_bodies(()));
index bccc19774e0d94048c6dcaa71d24b989d8103065..7e69ad21d034326a9c1fac72b80946e96a0c6fe8 100644 (file)
@@ -136,10 +136,7 @@ fn num_provided_lifetime_args(&self) -> usize {
             AngleBrackets::Missing => 0,
             // Only lifetime arguments can be implied
             AngleBrackets::Implied => self.gen_args.args.len(),
-            AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
-                hir::GenericArg::Lifetime(_) => acc + 1,
-                _ => acc,
-            }),
+            AngleBrackets::Available => self.gen_args.num_lifetime_params(),
         }
     }
 
@@ -148,10 +145,7 @@ fn num_provided_type_or_const_args(&self) -> usize {
             AngleBrackets::Missing => 0,
             // Only lifetime arguments can be implied
             AngleBrackets::Implied => 0,
-            AngleBrackets::Available => self.gen_args.args.iter().fold(0, |acc, arg| match arg {
-                hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => acc + 1,
-                _ => acc,
-            }),
+            AngleBrackets::Available => self.gen_args.num_generic_params(),
         }
     }
 
@@ -651,7 +645,9 @@ fn suggest_removing_args_or_generics(&self, err: &mut DiagnosticBuilder<'_>) {
             let mut found_redundant = false;
             for arg in self.gen_args.args {
                 match arg {
-                    hir::GenericArg::Type(_) | hir::GenericArg::Const(_) => {
+                    hir::GenericArg::Type(_)
+                    | hir::GenericArg::Const(_)
+                    | hir::GenericArg::Infer(_) => {
                         gen_arg_spans.push(arg.span());
                         if gen_arg_spans.len() > self.num_expected_type_or_const_args() {
                             found_redundant = true;
index c2d51c140b4ef0aa7d1c77af7615c7c25f034539..aff4e8fa82ac11e1fa84a542eb963806c991ea88 100644 (file)
@@ -103,7 +103,7 @@ changelog-seen = 2
 # the same format as above, but since these targets are experimental, they are
 # not built by default and the experimental Rust compilation targets that depend
 # on them will not work unless the user opts in to building them.
-#experimental-targets = "AVR"
+#experimental-targets = "AVR;M68k"
 
 # Cap the number of parallel linker invocations when compiling LLVM.
 # This can be useful when building LLVM with debug info, which significantly
index 482a497201de6d54fba41e8ce4876110ce80df0c..9ecbf0582319e845febdf4cca95e4d822c0bd7c6 100644 (file)
@@ -330,7 +330,11 @@ pub fn into_owned(self) -> <B as ToOwned>::Owned {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<B: ?Sized + ToOwned> Deref for Cow<'_, B> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<B: ?Sized + ToOwned> const Deref for Cow<'_, B>
+where
+    B::Owned: ~const Borrow<B>,
+{
     type Target = B;
 
     fn deref(&self) -> &B {
index 5f13c3bf30387bdb74c75ad497c00c35533a797f..54a157be0b96acdfecab5838f1385f0c1b939db1 100644 (file)
@@ -17,7 +17,13 @@ pub struct IntoIter<
     T,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
 > {
-    pub(crate) inner: VecDeque<T, A>,
+    inner: VecDeque<T, A>,
+}
+
+impl<T, A: Allocator> IntoIter<T, A> {
+    pub(super) fn new(inner: VecDeque<T, A>) -> Self {
+        IntoIter { inner }
+    }
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
index e4b28204158d9d3372ade952b5487eb1e96ebfd7..10144cc17bf306579ccc1b4e2272fb86b11a644d 100644 (file)
@@ -2827,7 +2827,7 @@ impl<T, A: Allocator> IntoIterator for VecDeque<T, A> {
     /// Consumes the `VecDeque` into a front-to-back iterator yielding elements by
     /// value.
     fn into_iter(self) -> IntoIter<T, A> {
-        IntoIter { inner: self }
+        IntoIter::new(self)
     }
 }
 
index 5767108d423c6c418a6f455ffb1d7a290cf68778..cae4dae708e59cf927a1b10c1e91c78551d3e2fd 100644 (file)
@@ -18,7 +18,6 @@
 #![feature(binary_heap_retain)]
 #![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
-#![feature(iter_map_while)]
 #![feature(slice_group_by)]
 #![feature(slice_partition_dedup)]
 #![feature(vec_spare_capacity)]
index 4f925f8d81dfa57067537217e501e1dff7433491..cc89bb66f91b2b4a640b0b525ca5d753e3346d7e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4f925f8d81dfa57067537217e501e1dff7433491
+Subproject commit cc89bb66f91b2b4a640b0b525ca5d753e3346d7e
diff --git a/library/core/primitive_docs/box_into_raw.md b/library/core/primitive_docs/box_into_raw.md
new file mode 100644 (file)
index 0000000..9dd0344
--- /dev/null
@@ -0,0 +1 @@
+../std/boxed/struct.Box.html#method.into_raw
diff --git a/library/core/primitive_docs/fs_file.md b/library/core/primitive_docs/fs_file.md
new file mode 100644 (file)
index 0000000..4023e34
--- /dev/null
@@ -0,0 +1 @@
+../std/fs/struct.File.html
diff --git a/library/core/primitive_docs/io_bufread.md b/library/core/primitive_docs/io_bufread.md
new file mode 100644 (file)
index 0000000..7beda2c
--- /dev/null
@@ -0,0 +1 @@
+../std/io/trait.BufRead.html
diff --git a/library/core/primitive_docs/io_read.md b/library/core/primitive_docs/io_read.md
new file mode 100644 (file)
index 0000000..b7ecf5e
--- /dev/null
@@ -0,0 +1 @@
+../std/io/trait.Read.html
diff --git a/library/core/primitive_docs/io_seek.md b/library/core/primitive_docs/io_seek.md
new file mode 100644 (file)
index 0000000..db0274d
--- /dev/null
@@ -0,0 +1 @@
+../std/io/trait.Seek.html
diff --git a/library/core/primitive_docs/io_write.md b/library/core/primitive_docs/io_write.md
new file mode 100644 (file)
index 0000000..92a3b88
--- /dev/null
@@ -0,0 +1 @@
+../std/io/trait.Write.html
diff --git a/library/core/primitive_docs/net_tosocketaddrs.md b/library/core/primitive_docs/net_tosocketaddrs.md
new file mode 100644 (file)
index 0000000..4daa10d
--- /dev/null
@@ -0,0 +1 @@
+../std/net/trait.ToSocketAddrs.html
diff --git a/library/core/primitive_docs/process_exit.md b/library/core/primitive_docs/process_exit.md
new file mode 100644 (file)
index 0000000..cae34d1
--- /dev/null
@@ -0,0 +1 @@
+../std/process/fn.exit.html
diff --git a/library/core/primitive_docs/string_string.md b/library/core/primitive_docs/string_string.md
new file mode 100644 (file)
index 0000000..303dc07
--- /dev/null
@@ -0,0 +1 @@
+../std/string/struct.String.html
index 4780d8dc7883ff0b17ddf2bb32faf32c3aaf230b..0a456ee1eb2d59fde0ac9d7c2b56382ee0a1da1a 100644 (file)
@@ -21,7 +21,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct EscapeDefault {
-    range: Range<usize>,
+    range: Range<u8>,
     data: [u8; 4],
 }
 
@@ -114,7 +114,7 @@ fn hexify(b: u8) -> u8 {
 impl Iterator for EscapeDefault {
     type Item = u8;
     fn next(&mut self) -> Option<u8> {
-        self.range.next().map(|i| self.data[i])
+        self.range.next().map(|i| self.data[i as usize])
     }
     fn size_hint(&self) -> (usize, Option<usize>) {
         self.range.size_hint()
@@ -126,7 +126,7 @@ fn last(mut self) -> Option<u8> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl DoubleEndedIterator for EscapeDefault {
     fn next_back(&mut self) -> Option<u8> {
-        self.range.next_back().map(|i| self.data[i])
+        self.range.next_back().map(|i| self.data[i as usize])
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -138,7 +138,9 @@ impl FusedIterator for EscapeDefault {}
 impl fmt::Display for EscapeDefault {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         // SAFETY: ok because `escape_default` created only valid utf-8 data
-        f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
+        f.write_str(unsafe {
+            from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
+        })
     }
 }
 
index ca1c0ae759892466228d0f072e48a6da7da78df6..f14c2a4641627ec4378bad32c91e0b129bd6bbc7 100644 (file)
@@ -2,7 +2,8 @@
 
 #[lang = "bool"]
 impl bool {
-    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+    /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
+    /// or `None` otherwise.
     ///
     /// # Examples
     ///
@@ -18,7 +19,8 @@ pub fn then_some<T>(self, t: T) -> Option<T> {
         if self { Some(t) } else { None }
     }
 
-    /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+    /// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html),
+    /// or `None` otherwise.
     ///
     /// # Examples
     ///
index 2adf6a549e6417b94349752487b39f76257fa727..e56b631dbaf8db537afb2bd8196e709ba074f396 100644 (file)
@@ -1916,7 +1916,8 @@ pub const fn get(&self) -> *mut T {
     /// ```
     #[inline(always)]
     #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")]
-    pub fn get_mut(&mut self) -> &mut T {
+    #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")]
+    pub const fn get_mut(&mut self) -> &mut T {
         &mut self.value
     }
 
index e6d3ac8f2d2c5d3637cb4fd144fc1572cedf691a..b1dd6aef97493e13500ce026a614005a1ee7c779 100644 (file)
@@ -24,7 +24,7 @@ impl char {
     /// decoding error.
     ///
     /// It can occur, for example, when giving ill-formed UTF-8 bytes to
-    /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy).
+    /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy).
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
 
@@ -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`](keyword.as.html):
+    /// [`as`](../std/keyword.as.html):
     ///
     /// ```
     /// let c = '💯';
@@ -372,7 +372,7 @@ pub fn to_digit(self, radix: u32) -> Option<u32> {
     /// println!("\\u{{2764}}");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
@@ -448,7 +448,7 @@ pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
     /// println!("\\n");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/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`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/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`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/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`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('c'.to_uppercase().to_string(), "C");
index 19faf9cddac6faa392a946742d00807d7441bf29..b02333b028850fd7a831adeb811e3bd6c7b37e61 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "clone"]
 #[rustc_diagnostic_item = "Clone"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
 pub trait Clone: Sized {
     /// Returns a copy of the value.
     ///
index 0a29843c9cf271b5ddd45c528748009d70903fff..166a8e3f28a4190e9adfeda75b90ec29153b8429 100644 (file)
@@ -582,6 +582,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
 )]
 #[doc(alias = "{:?}")]
 #[rustc_diagnostic_item = "debug_trait"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
 pub trait Debug {
     /// Formats the value using the given formatter.
     ///
index 8f89e1588048ffd07dbaf7d573e64aa38ebbed51..793b05fcf9529da6f7465bca7dbdf9f6e13e80c4 100644 (file)
@@ -10,7 +10,7 @@
 /// [`map_while`]: Iterator::map_while
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterators are lazy and do nothing unless consumed"]
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
 #[derive(Clone)]
 pub struct MapWhile<I, P> {
     iter: I,
@@ -23,14 +23,14 @@ pub(in crate::iter) fn new(iter: I, predicate: P) -> MapWhile<I, P> {
     }
 }
 
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
 impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("MapWhile").field("iter", &self.iter).finish()
     }
 }
 
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
 impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
 where
     P: FnMut(I::Item) -> Option<B>,
index f02d278aff5e4b980375a4000737a426d6f6e0a3..48e7dcfa7d9a30d838c275233a0f95f7645bb208 100644 (file)
@@ -45,7 +45,7 @@
 #[stable(feature = "iter_intersperse", since = "1.56.0")]
 pub use self::intersperse::{Intersperse, IntersperseWith};
 
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
 pub use self::map_while::MapWhile;
 
 #[unstable(feature = "trusted_random_access", issue = "none")]
index cd8a26025ffb6291543288cf0a859f034a93dc7a..d6f9edaa046c69e5922678b94d67a68f52373fe8 100644 (file)
 pub use self::adapters::Copied;
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
 pub use self::adapters::Flatten;
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
 pub use self::adapters::MapWhile;
 #[unstable(feature = "inplace_iteration", issue = "none")]
 pub use self::adapters::SourceIter;
index 330d3714247c5024d03c8ce9738dac403d282f0f..f884340f4e0bd02710d3d96684e8439ac34cacb9 100644 (file)
@@ -1116,7 +1116,6 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iter_map_while)]
     /// let a = [-1i32, 4, 0, 1];
     ///
     /// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
@@ -1147,7 +1146,6 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     /// Stopping after an initial [`None`]:
     ///
     /// ```
-    /// #![feature(iter_map_while)]
     /// use std::convert::TryFrom;
     ///
     /// let a = [0, 1, 2, -3, 4, 5, -6];
@@ -1165,7 +1163,6 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     /// removed:
     ///
     /// ```
-    /// #![feature(iter_map_while)]
     /// use std::convert::TryFrom;
     ///
     /// let a = [1, 2, -3, 4];
@@ -1191,7 +1188,7 @@ fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>
     ///
     /// [`fuse`]: Iterator::fuse
     #[inline]
-    #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+    #[stable(feature = "iter_map_while", since = "1.57.0")]
     fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
     where
         Self: Sized,
@@ -2172,8 +2169,9 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B
     /// If the iterator is empty, returns [`None`]; otherwise, returns the
     /// result of the reduction.
     ///
+    /// The reducing function is a closure with two arguments: an 'accumulator', and an element.
     /// For iterators with at least one element, this is the same as [`fold()`]
-    /// with the first element of the iterator as the initial value, folding
+    /// with the first element of the iterator as the initial accumulator value, folding
     /// every subsequent element into it.
     ///
     /// [`fold()`]: Iterator::fold
@@ -2187,8 +2185,8 @@ fn fold<B, F>(mut self, init: B, mut f: F) -> B
     ///     where I: Iterator,
     ///           I::Item: Ord,
     /// {
-    ///     iter.reduce(|a, b| {
-    ///         if a >= b { a } else { b }
+    ///     iter.reduce(|accum, item| {
+    ///         if accum >= item { accum } else { item }
     ///     })
     /// }
     /// let a = [10, 20, 5, -23, 0];
index 2c517371c2c9bbccf80bffc7880136e64f85c33e..e6bea462fa99a8a56441474eba5efb4aa0ee91fc 100644 (file)
@@ -214,7 +214,16 @@ pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
         if let Some(val) = self.get() {
             return Ok(val);
         }
-        let val = f()?;
+        /// Avoid inlining the initialization closure into the common path that fetches
+        /// the already initialized value
+        #[cold]
+        fn outlined_call<F, T, E>(f: F) -> Result<T, E>
+        where
+            F: FnOnce() -> Result<T, E>,
+        {
+            f()
+        }
+        let val = outlined_call(f)?;
         // Note that *some* forms of reentrant initialization might lead to
         // UB (see `reentrant_init` test). I believe that just removing this
         // `assert`, while keeping `set/get` would be sound, but it seems
index 06a409c6a2eb9d0fe98dce8b21c405be4c631854..265ba9f1bb91b69d1fc9c2b162b4a18a03db34d9 100644 (file)
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
 #![feature(doc_notable_trait)]
+#![feature(doc_primitive)]
 #![feature(exhaustive_patterns)]
 #![feature(extern_types)]
 #![feature(fundamental)]
@@ -355,3 +356,5 @@ pub mod arch {
         /* compiler built-in */
     }
 }
+
+include!("primitive_docs.rs");
index 82962a1fe13fc2ce59a3342904ee4044c286a627..a7ed5bfaf8598367492120435663c08676b55a0d 100644 (file)
@@ -99,17 +99,15 @@ pub trait Sized {
 /// `Unsize<dyn fmt::Debug>`.
 ///
 /// All implementations of `Unsize` are provided automatically by the compiler.
-///
-/// `Unsize` is implemented for:
-///
-/// - `[T; N]` is `Unsize<[T]>`
-/// - `T` is `Unsize<dyn Trait>` when `T: Trait`
-/// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
-///   - `T: Unsize<U>`
-///   - Foo is a struct
-///   - Only the last field of `Foo` has a type involving `T`
-///   - `T` is not part of the type of any other fields
-///   - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
+/// Those implementations are:
+///
+/// - Arrays `[T; N]` implement `Unsize<[T]>`.
+/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`.
+/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions
+///   are met:
+///   - `T: Unsize<U>`.
+///   - Only the last field of `Foo` has a type involving `T`.
+///   - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field.
 ///
 /// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
 /// "user-defined" containers such as [`Rc`] to contain dynamically-sized
index d86939454be5b0c4432dec7fe6c97a90da0c5e48..20b6453990d7519ce7199d49733b59fa0c899dd4 100644 (file)
@@ -145,7 +145,8 @@ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
 }
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> Deref for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for ManuallyDrop<T> {
     type Target = T;
     #[inline(always)]
     fn deref(&self) -> &T {
@@ -154,7 +155,8 @@ fn deref(&self) -> &T {
 }
 
 #[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
     #[inline(always)]
     fn deref_mut(&mut self) -> &mut T {
         &mut self.value
index be6d70320d407669839cae46e732bc1471becfa3..b078cdf5479d7ba536cfdefff4584cc369f4e44d 100644 (file)
 ///
 /// assert_eq!(u32::MAX, (zero - one).0);
 /// ```
+///
+/// # Layout
+///
+/// `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
 #[repr(transparent)]
index dcf3ce070ec6578f8b0a220ba78dae0755e1d3f1..fb4ec83bc287e7d42a4ccbf132365d8f910f3951 100644 (file)
@@ -76,7 +76,8 @@ pub trait Deref {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for &T {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for &T {
     type Target = T;
 
     #[rustc_diagnostic_item = "noop_method_deref"]
@@ -89,7 +90,8 @@ fn deref(&self) -> &T {
 impl<T: ?Sized> !DerefMut for &T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Deref for &mut T {
+#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
+impl<T: ?Sized> const Deref for &mut T {
     type Target = T;
 
     fn deref(&self) -> &T {
index 463bec37265d5035c7cbd34bb46d3cd3bc174070..7a8b04d6f3c13c4599201e5c1b6064d854604041 100644 (file)
     ($msg:literal $(,)?) => (
         $crate::panicking::panic($msg)
     ),
+    // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
     ($msg:expr $(,)?) => (
         $crate::panicking::panic_str($msg)
     ),
+    // Special-case the single-argument case for const_panic.
+    ("{}", $arg:expr $(,)?) => (
+        $crate::panicking::panic_display(&$arg)
+    ),
     ($fmt:expr, $($arg:tt)+) => (
         $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
     ),
     () => (
         $crate::panicking::panic("explicit panic")
     ),
+    // Special-case the single-argument case for const_panic.
+    ("{}", $arg:expr $(,)?) => (
+        $crate::panicking::panic_display(&$arg)
+    ),
     ($($t:tt)+) => (
         $crate::panicking::panic_fmt($crate::const_format_args!($($t)+))
     ),
index 02f32675247c3dba2addb111f9ceed4d73358b12..a6aa4bf43c865292e1764a6a6fa3a02826db2ae3 100644 (file)
@@ -60,6 +60,13 @@ pub fn panic_str(expr: &str) -> ! {
     panic_fmt(format_args!("{}", expr));
 }
 
+#[inline]
+#[track_caller]
+#[cfg_attr(not(bootstrap), lang = "panic_display")] // needed for const-evaluated panics
+pub fn panic_display<T: fmt::Display>(x: &T) -> ! {
+    panic_fmt(format_args!("{}", *x));
+}
+
 #[cold]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[track_caller]
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
new file mode 100644 (file)
index 0000000..0de9126
--- /dev/null
@@ -0,0 +1,1307 @@
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
+#[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[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.
+///
+/// # 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 it isn't.
+///
+/// ```
+/// let bool_val = true & false | false;
+/// assert!(!bool_val);
+/// ```
+///
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
+/// [`BitAnd`]: ops::BitAnd
+/// [`BitOr`]: ops::BitOr
+/// [`Not`]: ops::Not
+/// [`if`]: ../std/keyword.if.html
+///
+/// # Examples
+///
+/// A trivial example of the usage of `bool`:
+///
+/// ```
+/// let praise_the_borrow_checker = true;
+///
+/// // using the `if` conditional
+/// if praise_the_borrow_checker {
+///     println!("oh, yeah!");
+/// } else {
+///     println!("what?!!");
+/// }
+///
+/// // ... or, a match pattern
+/// match praise_the_borrow_checker {
+///     true => println!("keep praising!"),
+///     false => println!("you should praise!"),
+/// }
+/// ```
+///
+/// Also, since `bool` implements the [`Copy`] trait, we don't
+/// have to worry about the move semantics (just like the integer and float primitives).
+///
+/// Now an example of `bool` cast to integer type:
+///
+/// ```
+/// assert_eq!(true as i32, 1);
+/// assert_eq!(false as i32, 0);
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_bool {}
+
+#[doc(primitive = "never")]
+#[doc(alias = "!")]
+//
+/// The `!` type, also called "never".
+///
+/// `!` represents the type of computations which never resolve to any value at all. For example,
+/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and
+/// so returns `!`.
+///
+/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to
+/// write:
+///
+/// ```
+/// #![feature(never_type)]
+/// # fn foo() -> u32 {
+/// let x: ! = {
+///     return 123
+/// };
+/// # }
+/// ```
+///
+/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never
+/// assigned a value (because `return` returns from the entire function), `x` can be given type
+/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code
+/// would still be valid.
+///
+/// A more realistic usage of `!` is in this code:
+///
+/// ```
+/// # fn get_a_number() -> Option<u32> { None }
+/// # loop {
+/// let num: u32 = match get_a_number() {
+///     Some(num) => num,
+///     None => break,
+/// };
+/// # }
+/// ```
+///
+/// Both match arms must produce values of type [`u32`], but since `break` never produces a value
+/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another
+/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
+///
+/// [`u32`]: prim@u32
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
+///
+/// # `!` and generics
+///
+/// ## Infallible errors
+///
+/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
+/// trait:
+///
+/// ```
+/// trait FromStr: Sized {
+///     type Err;
+///     fn from_str(s: &str) -> Result<Self, Self::Err>;
+/// }
+/// ```
+///
+/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
+/// converting a string into a string will never result in an error, the appropriate type is `!`.
+/// (Currently the type actually used is an enum with no variants, though this is only because `!`
+/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of
+/// `!`, if we have to call [`String::from_str`] for some reason the result will be a
+/// [`Result<String, !>`] which we can unpack like this:
+///
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
+/// let Ok(s) = String::from_str("hello");
+/// ```
+///
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
+///
+/// ## Infinite loops
+///
+/// While [`Result<T, !>`] is very useful for removing errors, `!` can also be used to remove
+/// successes as well. If we think of [`Result<T, !>`] as "if this function returns, it has not
+/// errored," we get a very intuitive idea of [`Result<!, E>`] as well: if the function returns, it
+/// *has* errored.
+///
+/// For example, consider the case of a simple web server, which can be simplified to:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     let (client, request) = get_request().expect("disconnected");
+///     let response = request.process();
+///     response.send(client);
+/// }
+/// ```
+///
+/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection.
+/// Instead, we'd like to keep track of this error, like this:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     match get_request() {
+///         Err(err) => break err,
+///         Ok((client, request)) => {
+///             let response = request.process();
+///             response.send(client);
+///         },
+///     }
+/// }
+/// ```
+///
+/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it
+/// might be intuitive to simply return the error, we might want to wrap it in a [`Result<!, E>`]
+/// instead:
+///
+/// ```ignore (hypothetical-example)
+/// fn server_loop() -> Result<!, ConnectionError> {
+///     loop {
+///         let (client, request) = get_request()?;
+///         let response = request.process();
+///         response.send(client);
+///     }
+/// }
+/// ```
+///
+/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop
+/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok`
+/// because `!` coerces to `Result<!, ConnectionError>` automatically.
+///
+/// [`String::from_str`]: str::FromStr::from_str
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+/// [`FromStr`]: str::FromStr
+///
+/// # `!` and traits
+///
+/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
+/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!`
+/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other
+/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
+///
+/// ```compile_fail
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+///     unimplemented!()
+/// }
+/// ```
+///
+/// But this code does:
+///
+/// ```
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+///     if true {
+///         unimplemented!()
+///     } else {
+///         0
+///     }
+/// }
+/// ```
+///
+/// The reason is that, in the first example, there are many possible types that `!` could coerce
+/// to, because many types implement `Add<u32>`. However, in the second example,
+/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type
+/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375]
+/// for more information on this quirk of `!`.
+///
+/// [#36375]: https://github.com/rust-lang/rust/issues/36375
+///
+/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`]
+/// for example:
+///
+/// ```
+/// #![feature(never_type)]
+/// # use std::fmt;
+/// # trait Debug {
+/// #     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
+/// # }
+/// impl Debug for ! {
+///     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+///         *self
+///     }
+/// }
+/// ```
+///
+/// Once again we're using `!`'s ability to coerce into any other type, in this case
+/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be
+/// called (because there is no value of type `!` for it to be called with). Writing `*self`
+/// essentially tells the compiler "We know that this code can never be run, so just treat the
+/// entire function body as having type [`fmt::Result`]". This pattern can be used a lot when
+/// implementing traits for `!`. Generally, any trait which only has methods which take a `self`
+/// parameter should have such an impl.
+///
+/// On the other hand, one trait which would not be appropriate to implement is [`Default`]:
+///
+/// ```
+/// trait Default {
+///     fn default() -> Self;
+/// }
+/// ```
+///
+/// Since `!` has no values, it has no default value either. It's true that we could write an
+/// `impl` for this which simply panics, but the same is true for any type (we could `impl
+/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
+///
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
+/// [`Debug`]: fmt::Debug
+/// [`default()`]: Default::default
+///
+#[unstable(feature = "never_type", issue = "35121")]
+mod prim_never {}
+
+#[doc(primitive = "char")]
+/// A character type.
+///
+/// The `char` type represents a single character. More specifically, since
+/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
+/// scalar value]', which is similar to, but not the same as, a '[Unicode code
+/// point]'.
+///
+/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
+///
+/// This documentation describes a number of methods and trait implementations on the
+/// `char` type. For technical reasons, there is additional, separate
+/// documentation in [the `std::char` module](char/index.html) as well.
+///
+/// # Representation
+///
+/// `char` is always four bytes in size. This is a different representation than
+/// a given character would have as part of a [`String`]. For example:
+///
+/// ```
+/// let v = vec!['h', 'e', 'l', 'l', 'o'];
+///
+/// // five elements times four bytes for each element
+/// assert_eq!(20, v.len() * std::mem::size_of::<char>());
+///
+/// let s = String::from("hello");
+///
+/// // five elements times one byte per element
+/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
+/// ```
+///
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+///
+/// As always, remember that a human intuition for 'character' might not map to
+/// Unicode's definitions. For example, despite looking similar, the 'é'
+/// character is one Unicode code point while 'é' is two Unicode code points:
+///
+/// ```
+/// let mut chars = "é".chars();
+/// // U+00e9: 'latin small letter e with acute'
+/// assert_eq!(Some('\u{00e9}'), chars.next());
+/// assert_eq!(None, chars.next());
+///
+/// let mut chars = "é".chars();
+/// // U+0065: 'latin small letter e'
+/// assert_eq!(Some('\u{0065}'), chars.next());
+/// // U+0301: 'combining acute accent'
+/// assert_eq!(Some('\u{0301}'), chars.next());
+/// assert_eq!(None, chars.next());
+/// ```
+///
+/// This means that the contents of the first string above _will_ fit into a
+/// `char` while the contents of the second string _will not_. Trying to create
+/// a `char` literal with the contents of the second string gives an error:
+///
+/// ```text
+/// error: character literal may only contain one codepoint: 'é'
+/// let c = 'é';
+///         ^^^
+/// ```
+///
+/// Another implication of the 4-byte fixed size of a `char` is that
+/// per-`char` processing can end up using a lot more memory:
+///
+/// ```
+/// let s = String::from("love: ❤️");
+/// let v: Vec<char> = s.chars().collect();
+///
+/// assert_eq!(12, std::mem::size_of_val(&s[..]));
+/// assert_eq!(32, std::mem::size_of_val(&v[..]));
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_char {}
+
+#[doc(primitive = "unit")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// The `()` type, also called "unit".
+///
+/// The `()` type has exactly one value `()`, and is used when there
+/// is no other meaningful value that could be returned. `()` is most
+/// commonly seen implicitly: functions without a `-> ...` implicitly
+/// have return type `()`, that is, these are equivalent:
+///
+/// ```rust
+/// fn long() -> () {}
+///
+/// fn short() {}
+/// ```
+///
+/// The semicolon `;` can be used to discard the result of an
+/// expression at the end of a block, making the expression (and thus
+/// the block) evaluate to `()`. For example,
+///
+/// ```rust
+/// fn returns_i64() -> i64 {
+///     1i64
+/// }
+/// fn returns_unit() {
+///     1i64;
+/// }
+///
+/// let is_i64 = {
+///     returns_i64()
+/// };
+/// let is_unit = {
+///     returns_i64();
+/// };
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_unit {}
+
+#[doc(primitive = "pointer")]
+#[doc(alias = "ptr")]
+#[doc(alias = "*")]
+#[doc(alias = "*const")]
+#[doc(alias = "*mut")]
+//
+/// Raw, unsafe pointers, `*const T`, and `*mut T`.
+///
+/// *[See also the `std::ptr` module](ptr).*
+///
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
+/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
+/// dereferenced (using the `*` operator), it must be non-null and aligned.
+///
+/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
+/// [`write`] must be used if the type has drop glue and memory is not already
+/// initialized - otherwise `drop` would be called on the uninitialized memory.
+///
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
+///
+/// # Common ways to create raw pointers
+///
+/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
+///
+/// ```
+/// let my_num: i32 = 10;
+/// let my_num_ptr: *const i32 = &my_num;
+/// let mut my_speed: i32 = 88;
+/// let my_speed_ptr: *mut i32 = &mut my_speed;
+/// ```
+///
+/// To get a pointer to a boxed value, dereference the box:
+///
+/// ```
+/// let my_num: Box<i32> = Box::new(10);
+/// let my_num_ptr: *const i32 = &*my_num;
+/// let mut my_speed: Box<i32> = Box::new(88);
+/// let my_speed_ptr: *mut i32 = &mut *my_speed;
+/// ```
+///
+/// This does not take ownership of the original allocation
+/// and requires no resource management later,
+/// but you must not use the pointer after its lifetime.
+///
+/// ## 2. Consume a box (`Box<T>`).
+///
+/// The [`into_raw`] function consumes a box and returns
+/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
+///
+/// ```
+/// let my_speed: Box<i32> = Box::new(88);
+/// let my_speed: *mut i32 = Box::into_raw(my_speed);
+///
+/// // By taking ownership of the original `Box<T>` though
+/// // we are obligated to put it together later to be destroyed.
+/// unsafe {
+///     drop(Box::from_raw(my_speed));
+/// }
+/// ```
+///
+/// Note that here the call to [`drop`] is for clarity - it indicates
+/// that we are done with the given value and it should be destroyed.
+///
+/// ## 3. Create it using `ptr::addr_of!`
+///
+/// Instead of coercing a reference to a raw pointer, you can use the macros
+/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
+/// These macros allow you to create raw pointers to fields to which you cannot
+/// create a reference (without causing undefined behaviour), such as an
+/// unaligned field. This might be necessary if packed structs or uninitialized
+/// memory is involved.
+///
+/// ```
+/// #[derive(Debug, Default, Copy, Clone)]
+/// #[repr(C, packed)]
+/// struct S {
+///     aligned: u8,
+///     unaligned: u32,
+/// }
+/// let s = S::default();
+/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
+/// ```
+///
+/// ## 4. Get it from C.
+///
+/// ```
+/// # #![feature(rustc_private)]
+/// extern crate libc;
+///
+/// use std::mem;
+///
+/// unsafe {
+///     let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
+///     if my_num.is_null() {
+///         panic!("failed to allocate memory");
+///     }
+///     libc::free(my_num as *mut libc::c_void);
+/// }
+/// ```
+///
+/// Usually you wouldn't literally use `malloc` and `free` from Rust,
+/// but C APIs hand out a lot of pointers generally, so are a common source
+/// of raw pointers in Rust.
+///
+/// [`null`]: ptr::null
+/// [`null_mut`]: ptr::null_mut
+/// [`is_null`]: pointer::is_null
+/// [`offset`]: pointer::offset
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
+/// [`drop`]: mem::drop
+/// [`write`]: ptr::write
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_pointer {}
+
+#[doc(primitive = "array")]
+#[doc(alias = "[]")]
+#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
+#[doc(alias = "[T; N]")]
+/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
+/// non-negative compile-time constant size, `N`.
+///
+/// There are two syntactic forms for creating an array:
+///
+/// * A list with each element, i.e., `[x, y, z]`.
+/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
+///   The type of `x` must be [`Copy`].
+///
+/// Note that `[expr; 0]` is allowed, and produces an empty array.
+/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
+/// be mindful of side effects.
+///
+/// Arrays of *any* size implement the following traits if the element type allows it:
+///
+/// - [`Copy`]
+/// - [`Clone`]
+/// - [`Debug`]
+/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`)
+/// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`]
+/// - [`Hash`]
+/// - [`AsRef`], [`AsMut`]
+/// - [`Borrow`], [`BorrowMut`]
+///
+/// Arrays of sizes from 0 to 32 (inclusive) implement the [`Default`] trait
+/// if the element type allows it. As a stopgap, trait implementations are
+/// statically generated up to size 32.
+///
+/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
+/// an array. Indeed, this provides most of the API for working with arrays.
+/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// You can move elements out of an array with a [slice pattern]. If you want
+/// one element, see [`mem::replace`].
+///
+/// # Examples
+///
+/// ```
+/// let mut array: [i32; 3] = [0; 3];
+///
+/// array[1] = 1;
+/// array[2] = 2;
+///
+/// assert_eq!([1, 2], &array[1..]);
+///
+/// // This loop prints: 0 1 2
+/// for x in array {
+///     print!("{} ", x);
+/// }
+/// ```
+///
+/// You can also iterate over reference to the array's elements:
+///
+/// ```
+/// let array: [i32; 3] = [0; 3];
+///
+/// for x in &array { }
+/// ```
+///
+/// You can use a [slice pattern] to move elements out of an array:
+///
+/// ```
+/// fn move_away(_: String) { /* Do interesting things. */ }
+///
+/// let [john, roa] = ["John".to_string(), "Roa".to_string()];
+/// move_away(john);
+/// move_away(roa);
+/// ```
+///
+/// # 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](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];
+///
+/// // This creates a slice iterator, producing references to each value.
+/// for item in array.into_iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // The `array_into_iter` lint suggests this change for future compatibility:
+/// for item in array.iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // You can explicitly iterate an array by value using
+/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// 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
+/// // Rust 2021:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array.into_iter().enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// Future language versions might start treating the `array.into_iter()`
+/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using
+/// those older editions should still be written with this change in mind, to
+/// prevent breakage in the future. The safest way to accomplish this is to
+/// 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 [`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
+/// // Rust 2015 and 2018:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter() {
+///     let x: &i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array) {
+///     let x: i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array {
+///     let x: i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // IntoIter can also start a chain.
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// [slice]: prim@slice
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+/// [`Borrow`]: borrow::Borrow
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [slice pattern]: ../reference/patterns.html#slice-patterns
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_array {}
+
+#[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
+/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here
+/// means that elements are laid out so that every element is the same
+/// distance from its neighbors.
+///
+/// *[See also the `std::slice` module](crate::slice).*
+///
+/// Slices are a view into a block of memory represented as a pointer and a
+/// length.
+///
+/// ```
+/// // slicing a Vec
+/// let vec = vec![1, 2, 3];
+/// let int_slice = &vec[..];
+/// // coercing an array to a slice
+/// let str_slice: &[&str] = &["one", "two", "three"];
+/// ```
+///
+/// Slices are either mutable or shared. The shared slice type is `&[T]`,
+/// while the mutable slice type is `&mut [T]`, where `T` represents the element
+/// type. For example, you can mutate the block of memory that a mutable slice
+/// points to:
+///
+/// ```
+/// let mut x = [1, 2, 3];
+/// let x = &mut x[..]; // Take a full slice of `x`.
+/// x[1] = 7;
+/// assert_eq!(x, &[1, 7, 3]);
+/// ```
+///
+/// As slices store the length of the sequence they refer to, they have twice
+/// the size of pointers to [`Sized`](marker/trait.Sized.html) types.
+/// Also see the reference on
+/// [dynamically sized types](../reference/dynamically-sized-types.html).
+///
+/// ```
+/// # use std::rc::Rc;
+/// let pointer_size = std::mem::size_of::<&u8>();
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_slice {}
+
+#[doc(primitive = "str")]
+//
+/// String slices.
+///
+/// *[See also the `std::str` module](crate::str).*
+///
+/// The `str` type, also called a 'string slice', is the most primitive string
+/// type. It is usually seen in its borrowed form, `&str`. It is also the type
+/// of string literals, `&'static str`.
+///
+/// String slices are always valid UTF-8.
+///
+/// # Examples
+///
+/// String literals are string slices:
+///
+/// ```
+/// let hello = "Hello, world!";
+///
+/// // with an explicit type annotation
+/// let hello: &'static str = "Hello, world!";
+/// ```
+///
+/// They are `'static` because they're stored directly in the final binary, and
+/// so will be valid for the `'static` duration.
+///
+/// # Representation
+///
+/// A `&str` is made up of two components: a pointer to some bytes, and a
+/// length. You can look at these with the [`as_ptr`] and [`len`] methods:
+///
+/// ```
+/// use std::slice;
+/// use std::str;
+///
+/// let story = "Once upon a time...";
+///
+/// let ptr = story.as_ptr();
+/// let len = story.len();
+///
+/// // story has nineteen bytes
+/// assert_eq!(19, len);
+///
+/// // We can re-build a str out of ptr and len. This is all unsafe because
+/// // we are responsible for making sure the two components are valid:
+/// let s = unsafe {
+///     // First, we build a &[u8]...
+///     let slice = slice::from_raw_parts(ptr, len);
+///
+///     // ... and then convert that slice into a string slice
+///     str::from_utf8(slice)
+/// };
+///
+/// assert_eq!(s, Ok(story));
+/// ```
+///
+/// [`as_ptr`]: str::as_ptr
+/// [`len`]: str::len
+///
+/// Note: This example shows the internals of `&str`. `unsafe` should not be
+/// used to get a string slice under normal circumstances. Use `as_str`
+/// instead.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_str {}
+
+#[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// A finite heterogeneous sequence, `(T, U, ..)`.
+///
+/// Let's cover each of those in turn:
+///
+/// Tuples are *finite*. In other words, a tuple has a length. Here's a tuple
+/// of length `3`:
+///
+/// ```
+/// ("hello", 5, 'c');
+/// ```
+///
+/// 'Length' is also sometimes called 'arity' here; each tuple of a different
+/// length is a different, distinct type.
+///
+/// Tuples are *heterogeneous*. This means that each element of the tuple can
+/// have a different type. In that tuple above, it has the type:
+///
+/// ```
+/// # let _:
+/// (&'static str, i32, char)
+/// # = ("hello", 5, 'c');
+/// ```
+///
+/// Tuples are a *sequence*. This means that they can be accessed by position;
+/// this is called 'tuple indexing', and it looks like this:
+///
+/// ```rust
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// assert_eq!(tuple.1, 5);
+/// assert_eq!(tuple.2, 'c');
+/// ```
+///
+/// The sequential nature of the tuple applies to its implementations of various
+/// 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).
+///
+/// # Trait implementations
+///
+/// If every type inside a tuple implements one of the following traits, then a
+/// tuple itself also implements it.
+///
+/// * [`Clone`]
+/// * [`Copy`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Debug`]
+/// * [`Default`]
+/// * [`Hash`]
+///
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only
+/// implemented on tuples of arity 12 or less. In the future, this may change.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// ```
+///
+/// Tuples are often used as a return type when you want to return more than
+/// one value:
+///
+/// ```
+/// fn calculate_point() -> (i32, i32) {
+///     // Don't do a calculation, that's not the point of the example
+///     (4, 5)
+/// }
+///
+/// let point = calculate_point();
+///
+/// assert_eq!(point.0, 4);
+/// assert_eq!(point.1, 5);
+///
+/// // Combining this with patterns can be nicer.
+///
+/// let (x, y) = calculate_point();
+///
+/// assert_eq!(x, 4);
+/// assert_eq!(y, 5);
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_tuple {}
+
+#[doc(primitive = "f32")]
+/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
+///
+/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
+/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
+/// (such as `i32`), floating point types can represent non-integer numbers,
+/// too.
+///
+/// However, being able to represent this wide range of numbers comes at the
+/// cost of precision: floats can only represent some of the real numbers and
+/// calculation with floats round to a nearby representable number. For example,
+/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results
+/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented
+/// as `f32`. Note, however, that printing floats with `println` and friends will
+/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
+/// print `0.2`.
+///
+/// Additionally, `f32` can represent some special values:
+///
+/// - −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a
+///   possible value. For comparison −0.0 = +0.0, but floating point operations can carry
+///   the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and
+///   a negative number rounded to a value smaller than a float can represent also produces −0.0.
+/// - [∞](#associatedconstant.INFINITY) and
+///   [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
+///   like `1.0 / 0.0`.
+/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
+///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
+///   behavior: it is unequal to any float, including itself! It is also neither
+///   smaller nor greater than any float, making it impossible to sort. Lastly,
+///   it is considered infectious as almost all calculations where one of the
+///   operands is NaN will also result in NaN.
+///
+/// For more information on floating point numbers, see [Wikipedia][wikipedia].
+///
+/// *[See also the `std::f32::consts` module](crate::f32::consts).*
+///
+/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f32 {}
+
+#[doc(primitive = "f64")]
+/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
+///
+/// This type is very similar to [`f32`], but has increased
+/// precision by using twice as many bits. Please see [the documentation for
+/// `f32`][`f32`] or [Wikipedia on double precision
+/// values][wikipedia] for more information.
+///
+/// *[See also the `std::f64::consts` module](crate::f64::consts).*
+///
+/// [`f32`]: prim@f32
+/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f64 {}
+
+#[doc(primitive = "i8")]
+//
+/// The 8-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i8 {}
+
+#[doc(primitive = "i16")]
+//
+/// The 16-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i16 {}
+
+#[doc(primitive = "i32")]
+//
+/// The 32-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i32 {}
+
+#[doc(primitive = "i64")]
+//
+/// The 64-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i64 {}
+
+#[doc(primitive = "i128")]
+//
+/// The 128-bit signed integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_i128 {}
+
+#[doc(primitive = "u8")]
+//
+/// The 8-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u8 {}
+
+#[doc(primitive = "u16")]
+//
+/// The 16-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u16 {}
+
+#[doc(primitive = "u32")]
+//
+/// The 32-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u32 {}
+
+#[doc(primitive = "u64")]
+//
+/// The 64-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u64 {}
+
+#[doc(primitive = "u128")]
+//
+/// The 128-bit unsigned integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_u128 {}
+
+#[doc(primitive = "isize")]
+//
+/// The pointer-sized signed integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_isize {}
+
+#[doc(primitive = "usize")]
+//
+/// The pointer-sized unsigned integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_usize {}
+
+#[doc(primitive = "reference")]
+#[doc(alias = "&")]
+#[doc(alias = "&mut")]
+//
+/// 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`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/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,
+/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/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
+/// calling, and indexing work the same (save for mutability rules, of course). In addition, the
+/// comparison operators transparently defer to the referent's implementation, allowing references
+/// to be compared the same as owned values.
+///
+/// References have a lifetime attached to them, which represents the scope for which the borrow is
+/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or
+/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the
+/// total life of the program. For example, string literals have a `'static` lifetime because the
+/// text data is embedded into the binary of the program, rather than in an allocation that needs
+/// to be dynamically managed.
+///
+/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
+/// references with longer lifetimes can be freely coerced into references with shorter ones.
+///
+/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
+/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
+/// [`PartialEq`] compares values.
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(five_ref == other_five_ref);
+///
+/// assert!(ptr::eq(five_ref, same_five_ref));
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
+/// For more information on how to use references, see [the book's section on "References and
+/// Borrowing"][book-refs].
+///
+/// [book-refs]: ../book/ch04-02-references-and-borrowing.html
+///
+/// # Trait implementations
+///
+/// The following traits are implemented for all `&T`, regardless of the type of its referent:
+///
+/// * [`Copy`]
+/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!)
+/// * [`Deref`]
+/// * [`Borrow`]
+/// * [`Pointer`]
+///
+/// [`Deref`]: ops::Deref
+/// [`Borrow`]: borrow::Borrow
+/// [`Pointer`]: fmt::Pointer
+///
+/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating
+/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its
+/// referent:
+///
+/// * [`DerefMut`]
+/// * [`BorrowMut`]
+///
+/// [`DerefMut`]: ops::DerefMut
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
+///
+/// The following traits are implemented on `&T` references if the underlying `T` also implements
+/// that trait:
+///
+/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`AsRef`]
+/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`)
+/// * [`Hash`]
+/// * [`ToSocketAddrs`]
+///
+/// [`std::fmt`]: fmt
+/// ['Pointer`]: fmt::Pointer
+/// [`Hash`]: hash::Hash
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
+///
+/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
+/// implements that trait:
+///
+/// * [`AsMut`]
+/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`)
+/// * [`fmt::Write`]
+/// * [`Iterator`]
+/// * [`DoubleEndedIterator`]
+/// * [`ExactSizeIterator`]
+/// * [`FusedIterator`]
+/// * [`TrustedLen`]
+/// * [`Send`] \(note that `&T` references only get `Send` if <code>T: [Sync]</code>)
+/// * [`io::Write`]
+/// * [`Read`]
+/// * [`Seek`]
+/// * [`BufRead`]
+///
+/// [`FusedIterator`]: iter::FusedIterator
+/// [`TrustedLen`]: iter::TrustedLen
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
+///
+/// Note that due to method call deref coercion, simply calling a trait method will act like they
+/// work on references as well as they do on owned values! The implementations described here are
+/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
+/// locally known.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_ref {}
+
+#[doc(primitive = "fn")]
+//
+/// Function pointers, like `fn(usize) -> bool`.
+///
+/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].*
+///
+/// [`Fn`]: ops::Fn
+/// [`FnMut`]: ops::FnMut
+/// [`FnOnce`]: ops::FnOnce
+///
+/// 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()>`](core::option#options-and-pointers-nullable-pointers)
+/// with your required signature.
+///
+/// ### Safety
+///
+/// Plain function pointers are obtained by casting either plain functions, or closures that don't
+/// capture an environment:
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let ptr: fn(usize) -> usize = add_one;
+/// assert_eq!(ptr(5), 6);
+///
+/// let clos: fn(usize) -> usize = |x| x + 5;
+/// assert_eq!(clos(5), 10);
+/// ```
+///
+/// In addition to varying based on their signature, function pointers come in two flavors: safe
+/// and unsafe. Plain `fn()` function pointers can only point to safe functions,
+/// while `unsafe fn()` function pointers can point to safe or unsafe functions.
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// unsafe fn add_one_unsafely(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let safe_ptr: fn(usize) -> usize = add_one;
+///
+/// //ERROR: mismatched types: expected normal fn, found unsafe fn
+/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely;
+///
+/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
+/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
+/// ```
+///
+/// ### ABI
+///
+/// On top of that, function pointers can vary based on what ABI they use. This
+/// is achieved by adding the `extern` keyword before the type, followed by the
+/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
+/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
+/// type `extern "C" fn()`.
+///
+/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
+/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
+/// ABI.
+///
+/// For more information and a list of supported ABIs, see [the nomicon's
+/// section on foreign calling conventions][nomicon-abi].
+///
+/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+///
+/// ### Variadic functions
+///
+/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
+/// to be called with a variable number of arguments. Normal Rust functions, even those with an
+/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
+/// variadic functions][nomicon-variadic].
+///
+/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
+///
+/// ### Creating function pointers
+///
+/// When `bar` is the name of a function, then the expression `bar` is *not* a
+/// function pointer. Rather, it denotes a value of an unnameable type that
+/// uniquely identifies the function `bar`. The value is zero-sized because the
+/// type already identifies the function. This has the advantage that "calling"
+/// the value (it implements the `Fn*` traits) does not require dynamic
+/// dispatch.
+///
+/// This zero-sized type *coerces* to a regular function pointer. For example:
+///
+/// ```rust
+/// use std::mem;
+///
+/// fn bar(x: i32) {}
+///
+/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
+/// assert_eq!(mem::size_of_val(&not_bar_ptr), 0);
+///
+/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
+/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
+///
+/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
+/// ```
+///
+/// The last line shows that `&bar` is not a function pointer either. Rather, it
+/// is a reference to the function-specific ZST. `&bar` is basically never what you
+/// want when `bar` is a function.
+///
+/// ### Traits
+///
+/// Function pointers implement the following traits:
+///
+/// * [`Clone`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Hash`]
+/// * [`Pointer`]
+/// * [`Debug`]
+///
+/// [`Hash`]: hash::Hash
+/// [`Pointer`]: fmt::Pointer
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change.
+///
+/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
+/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
+/// are specially known to the compiler.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_fn {}
index b67038a7d5c2c491adc4568f3df45f37634768fc..a04e479e8570dc542b02066998b52266c096e18a 100644 (file)
@@ -2257,9 +2257,9 @@ pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     /// assert!(match r { Ok(1..=4) => true, _ => false, });
     /// ```
     // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is
-    // in crate `alloc`, and as such doesn't exists yet when building `core`.
-    // links to downstream crate: #74481. Since primitives are only documented in
-    // libstd (#73423), this never leads to broken links in practice.
+    // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481.
+    // This breaks links when slice is displayed in core, but changing it to use relative links
+    // would break when the item is re-exported. So allow the core links to be broken for now.
     #[allow(rustdoc::broken_intra_doc_links)]
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
     #[inline]
index 7580010a28b4a5394ef5665d09f0a0a12a509e62..9567479c8137b5d4f0a7e8e0f07d7ee8edc0da12 100644 (file)
@@ -653,6 +653,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 fn test_formatting_parameters_are_forwarded() {
     use std::collections::{BTreeMap, BTreeSet};
     #[derive(Debug)]
+    #[allow(dead_code)]
     struct Foo {
         bar: u32,
         baz: u32,
index 19bcc45108dfd5225761723e0c6b7bb64fbb0eaa..cd3aed4cd28f81a7d90c9f7fc15cfb2a99d97d19 100644 (file)
@@ -50,7 +50,6 @@
 #![feature(iter_partition_in_place)]
 #![feature(iter_is_partitioned)]
 #![feature(iter_order_by)]
-#![feature(iter_map_while)]
 #![feature(const_mut_refs)]
 #![feature(const_pin)]
 #![feature(const_slice_from_raw_parts)]
index 7001e827ad8456778b1225f190a2fcdf596551d2..bb05506defd0778c8f1f24e72d2a9d1617a64121 100644 (file)
@@ -162,6 +162,8 @@ fn sub(
                 fn source($self: $S::Span) -> $S::Span;
                 fn start($self: $S::Span) -> LineColumn;
                 fn end($self: $S::Span) -> LineColumn;
+                fn before($self: $S::Span) -> $S::Span;
+                fn after($self: $S::Span) -> $S::Span;
                 fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>;
                 fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
                 fn source_text($self: $S::Span) -> Option<String>;
index 243922b18b565dfd0a5b55fdf944f04d9f7aa555..e21a1507a62e200689e9a2d182d2673461baaa0f 100644 (file)
@@ -357,6 +357,18 @@ pub fn end(&self) -> LineColumn {
         self.0.end().add_1_to_column()
     }
 
+    /// Creates an empty span pointing to directly before this span.
+    #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+    pub fn before(&self) -> Span {
+        Span(self.0.before())
+    }
+
+    /// Creates an empty span pointing to directly after this span.
+    #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+    pub fn after(&self) -> Span {
+        Span(self.0.after())
+    }
+
     /// Creates a new span encompassing `self` and `other`.
     ///
     /// Returns `None` if `self` and `other` are from different files.
diff --git a/library/std/primitive_docs/box_into_raw.md b/library/std/primitive_docs/box_into_raw.md
new file mode 100644 (file)
index 0000000..307b9c8
--- /dev/null
@@ -0,0 +1 @@
+Box::into_raw
diff --git a/library/std/primitive_docs/fs_file.md b/library/std/primitive_docs/fs_file.md
new file mode 100644 (file)
index 0000000..13e4540
--- /dev/null
@@ -0,0 +1 @@
+fs::File
diff --git a/library/std/primitive_docs/io_bufread.md b/library/std/primitive_docs/io_bufread.md
new file mode 100644 (file)
index 0000000..bb688e3
--- /dev/null
@@ -0,0 +1 @@
+io::BufRead
diff --git a/library/std/primitive_docs/io_read.md b/library/std/primitive_docs/io_read.md
new file mode 100644 (file)
index 0000000..5118d7c
--- /dev/null
@@ -0,0 +1 @@
+io::Read
diff --git a/library/std/primitive_docs/io_seek.md b/library/std/primitive_docs/io_seek.md
new file mode 100644 (file)
index 0000000..122e6df
--- /dev/null
@@ -0,0 +1 @@
+io::Seek
diff --git a/library/std/primitive_docs/io_write.md b/library/std/primitive_docs/io_write.md
new file mode 100644 (file)
index 0000000..15dfc90
--- /dev/null
@@ -0,0 +1 @@
+io::Write
diff --git a/library/std/primitive_docs/net_tosocketaddrs.md b/library/std/primitive_docs/net_tosocketaddrs.md
new file mode 100644 (file)
index 0000000..a01f318
--- /dev/null
@@ -0,0 +1 @@
+net::ToSocketAddrs
diff --git a/library/std/primitive_docs/process_exit.md b/library/std/primitive_docs/process_exit.md
new file mode 100644 (file)
index 0000000..565a713
--- /dev/null
@@ -0,0 +1 @@
+process::exit
diff --git a/library/std/primitive_docs/string_string.md b/library/std/primitive_docs/string_string.md
new file mode 100644 (file)
index 0000000..ce7815f
--- /dev/null
@@ -0,0 +1 @@
+string::String
index 130bb5cb2b3c2b77f6b7402330dd2ded199be0f7..71645aadb1d88b717eb03e341be65ef07a24982b 100644 (file)
 //! Iterators also provide a series of *adapter* methods for performing common
 //! threads to sequences. Among the adapters are functional favorites like `map`,
 //! `fold`, `skip` and `take`. Of particular interest to collections is the
-//! `rev` adapter, that reverses any iterator that supports this operation. Most
+//! `rev` adapter, which reverses any iterator that supports this operation. Most
 //! collections provide reversible iterators as the way to iterate over them in
 //! reverse order.
 //!
index e343073d2150879d87cab768a35cece48d98510f..40b46878cd8ba8c270f6780eafa2088c753a4321 100644 (file)
@@ -879,6 +879,7 @@ pub mod consts {
     /// - x86_64
     /// - arm
     /// - aarch64
+    /// - m68k
     /// - mips
     /// - mips64
     /// - powerpc
index ec9f012295000902e044f21c4ef7900d52adf4e0..cc4ea27e57e8d36d8c4f0d314bec127dc9540c26 100644 (file)
@@ -31,6 +31,7 @@
 use crate::str;
 use crate::string;
 use crate::sync::Arc;
+use crate::time;
 
 /// `Error` is a trait representing the basic expectations for error values,
 /// i.e., values of type `E` in [`Result<T, E>`].
@@ -182,7 +183,7 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     ///
     /// impl fmt::Display for AnError {
     ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f , "An error")
+    ///         write!(f, "An error")
     ///     }
     /// }
     ///
@@ -215,7 +216,7 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     ///
     /// impl fmt::Display for AnError {
     ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-    ///         write!(f , "An error")
+    ///         write!(f, "An error")
     ///     }
     /// }
     ///
@@ -598,7 +599,7 @@ fn description(&self) -> &str {
 impl Error for alloc::collections::TryReserveError {}
 
 #[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for core::time::FromSecsError {}
+impl Error for time::FromSecsError {}
 
 // Copied from `any.rs`.
 impl dyn Error + 'static {
index de05c377852950120a0d70655d2ab94c87a53248..3b9175503080c1e330b2b65a2d67ba420b101a19 100644 (file)
@@ -915,6 +915,7 @@ fn from(s: CString) -> Box<CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<CString> for Cow<'a, CStr> {
+    /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: CString) -> Cow<'a, CStr> {
         Cow::Owned(s)
@@ -923,6 +924,7 @@ fn from(s: CString) -> Cow<'a, CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<&'a CStr> for Cow<'a, CStr> {
+    /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: &'a CStr) -> Cow<'a, CStr> {
         Cow::Borrowed(s)
@@ -931,6 +933,7 @@ fn from(s: &'a CStr) -> Cow<'a, CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<&'a CString> for Cow<'a, CStr> {
+    /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: &'a CString) -> Cow<'a, CStr> {
         Cow::Borrowed(s.as_c_str())
index f6c2b499567abf9b245c42903ec5c98bd10cf780..d290c3c466035d5e2da432db494d263af24218b9 100644 (file)
@@ -468,9 +468,6 @@ struct ProgrammableSink {
     // Writes append to this slice
     pub buffer: Vec<u8>,
 
-    // Flush sets this flag
-    pub flushed: bool,
-
     // If true, writes will always be an error
     pub always_write_error: bool,
 
@@ -520,7 +517,6 @@ fn flush(&mut self) -> io::Result<()> {
         if self.always_flush_error {
             Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error"))
         } else {
-            self.flushed = true;
             Ok(())
         }
     }
index e8466fa06b899470cb213eb6ea295fdc1d6d86b6..4a35d36a9def72f284b48244219b347a9d140e80 100644 (file)
@@ -1611,7 +1611,7 @@ fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
     /// encountered.
     ///
     /// This method is primarily used to interface with the
-    /// [`format_args!()`] macro, but it is rare that this should
+    /// [`format_args!()`] macro, and it is rare that this should
     /// explicitly be called. The [`write!()`] macro should be favored to
     /// invoke this method instead.
     ///
index 3af941f59b68918d1417e444428112cdc662e17a..2e93807037464af71fddb3fe7c9004b5b2fcca23 100644 (file)
@@ -77,7 +77,7 @@ mod as_keyword {}
 ///     '_inner: for j in 1..=200 {
 ///         println!("    inner iteration (j): {}", j);
 ///         if j >= 3 {
-///             // breaks from inner loop, let's outer loop continue.
+///             // breaks from inner loop, lets outer loop continue.
 ///             break;
 ///         }
 ///         if i >= 2 {
index 83c6ba0e6ea450e83f76ddfdb58ff26d4063fcda..f69baba9e733f748d140972e08d0e2269904f2b7 100644 (file)
 #![feature(atomic_mut_ptr)]
 #![feature(auto_traits)]
 #![feature(bench_black_box)]
+#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(c_unwind)]
 #![feature(c_variadic)]
 #![feature(const_trait_impl)]
 #![feature(container_error_extra)]
 #![feature(core_intrinsics)]
+#![feature(core_panic)]
 #![feature(custom_test_frameworks)]
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
index 5b4a9fa7979de644cb0cc043114071cc53dfb480..223726d45d72a4ffe7ee2ad5897c7e97575cbbda 100644 (file)
@@ -96,6 +96,18 @@ pub struct Incoming<'a> {
     listener: &'a TcpListener,
 }
 
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
+///
+/// This `struct` is created by the [`TcpListener::into_incoming`] method.
+/// See its documentation for more.
+///
+/// [`accept`]: TcpListener::accept
+#[derive(Debug)]
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+pub struct IntoIncoming {
+    listener: TcpListener,
+}
+
 impl TcpStream {
     /// Opens a TCP connection to a remote host.
     ///
@@ -845,6 +857,37 @@ pub fn incoming(&self) -> Incoming<'_> {
         Incoming { listener: self }
     }
 
+    /// Turn this into an iterator over the connections being received on this
+    /// listener.
+    ///
+    /// The returned iterator will never return [`None`] and will also not yield
+    /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+    /// calling [`TcpListener::accept`] in a loop.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(tcplistener_into_incoming)]
+    /// use std::net::{TcpListener, TcpStream};
+    ///
+    /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> {
+    ///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    ///     listener.into_incoming()
+    ///         .filter_map(Result::ok) /* Ignore failed connections */
+    /// }
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     for stream in listen_on(80) {
+    ///         /* handle the connection here */
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+    pub fn into_incoming(self) -> IntoIncoming {
+        IntoIncoming { listener: self }
+    }
+
     /// Sets the value for the `IP_TTL` option on this socket.
     ///
     /// This value sets the time-to-live field that is used in every packet sent
@@ -982,6 +1025,14 @@ fn next(&mut self) -> Option<io::Result<TcpStream>> {
     }
 }
 
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+impl Iterator for IntoIncoming {
+    type Item = io::Result<TcpStream>;
+    fn next(&mut self) -> Option<io::Result<TcpStream>> {
+        Some(self.listener.accept().map(|p| p.0))
+    }
+}
+
 impl AsInner<net_imp::TcpListener> for TcpListener {
     fn as_inner(&self) -> &net_imp::TcpListener {
         &self.0
index 9b7af97616c9d304b77d9060e1c113469dfdb621..9d18ccbeb2494025374a3f04b99dcd4a60e62eef 100644 (file)
@@ -1,4 +1,6 @@
-//! Linux-specific extensions to primitives in the `std::fs` module.
+//! Linux-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
 
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
index e3e7143c851efaebb92d1a69b3e6864238a1d6cf..540363c03494e1aeed25f9d19b776c424c27bd4d 100644 (file)
@@ -1,4 +1,6 @@
-//! Linux-specific extensions to primitives in the `std::process` module.
+//! Linux-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
 
 #![unstable(feature = "linux_pidfd", issue = "82971")]
 
index 5b68a7e126268d9c33563c2587c740b9da67aa5c..cd92dcabdf5209bd6e998a3c73d92d7aa475102f 100644 (file)
@@ -27,6 +27,7 @@
 #[cfg(any(
     target_arch = "x86",
     target_arch = "le32",
+    target_arch = "m68k",
     target_arch = "powerpc",
     target_arch = "sparc",
     target_arch = "arm",
index 79e6967300767e463a5b6c06f5b2b663c9742809..069a5376a441c9062b8e945ba0f7610b46ddcbc4 100644 (file)
 // of a macro that is not vendored by Rust and included in the toolchain.
 // See https://github.com/rust-analyzer/rust-analyzer/issues/6038.
 
+// On certain platforms right now the "main modules" modules that are
+// documented don't compile (missing things in `libc` which is empty),
+// so just omit them with an empty module and add the "unstable" attribute.
+
+// Unix, linux, wasi and windows are handled a bit differently.
 #[cfg(all(
     doc,
-    not(any(
+    any(
         all(target_arch = "wasm32", not(target_os = "wasi")),
         all(target_vendor = "fortanix", target_env = "sgx")
-    ))
+    )
 ))]
-#[path = "."]
-mod doc {
-    // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi`
-    // modules as these are the "main modules" that are used across platforms,
-    // so these modules are enabled when `cfg(doc)` is set.
-    // This should help show platform-specific functionality in a hopefully cross-platform
-    // way in the documentation.
-
-    pub mod unix;
-
-    pub mod linux;
-
-    pub mod wasi;
-
-    pub mod windows;
-}
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod unix {}
 #[cfg(all(
     doc,
     any(
@@ -40,87 +31,115 @@ mod doc {
         all(target_vendor = "fortanix", target_env = "sgx")
     )
 ))]
-mod doc {
-    // On certain platforms right now the "main modules" modules that are
-    // documented don't compile (missing things in `libc` which is empty),
-    // so just omit them with an empty module.
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod unix {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod linux {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod wasi {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod windows {}
-}
-#[cfg(doc)]
-#[stable(feature = "os", since = "1.0.0")]
-pub use doc::*;
-
-#[cfg(not(doc))]
-#[path = "."]
-mod imp {
-    // If we're not documenting std then we only expose modules appropriate for the
-    // current platform.
-
-    #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
-    pub mod fortanix_sgx;
-
-    #[cfg(target_os = "hermit")]
-    #[path = "hermit/mod.rs"]
-    pub mod unix;
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod linux {}
+#[cfg(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod wasi {}
+#[cfg(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod windows {}
 
-    #[cfg(target_os = "android")]
-    pub mod android;
-    #[cfg(target_os = "dragonfly")]
-    pub mod dragonfly;
-    #[cfg(target_os = "emscripten")]
-    pub mod emscripten;
-    #[cfg(target_os = "espidf")]
-    pub mod espidf;
-    #[cfg(target_os = "freebsd")]
-    pub mod freebsd;
-    #[cfg(target_os = "fuchsia")]
-    pub mod fuchsia;
-    #[cfg(target_os = "haiku")]
-    pub mod haiku;
-    #[cfg(target_os = "illumos")]
-    pub mod illumos;
-    #[cfg(target_os = "ios")]
-    pub mod ios;
-    #[cfg(target_os = "l4re")]
-    pub mod linux;
-    #[cfg(target_os = "linux")]
-    pub mod linux;
-    #[cfg(target_os = "macos")]
-    pub mod macos;
-    #[cfg(target_os = "netbsd")]
-    pub mod netbsd;
-    #[cfg(target_os = "openbsd")]
-    pub mod openbsd;
-    #[cfg(target_os = "redox")]
-    pub mod redox;
-    #[cfg(target_os = "solaris")]
-    pub mod solaris;
-    #[cfg(unix)]
-    pub mod unix;
+// unix
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(target_os = "hermit")]
+#[path = "hermit/mod.rs"]
+pub mod unix;
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
+pub mod unix;
 
-    #[cfg(target_os = "vxworks")]
-    pub mod vxworks;
+// linux
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(target_os = "linux", target_os = "l4re", doc))]
+pub mod linux;
 
-    #[cfg(target_os = "wasi")]
-    pub mod wasi;
+// wasi
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(target_os = "wasi", doc))]
+pub mod wasi;
 
-    #[cfg(windows)]
-    pub mod windows;
-}
-#[cfg(not(doc))]
-#[stable(feature = "os", since = "1.0.0")]
-pub use imp::*;
+// windows
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(windows, doc))]
+pub mod windows;
+
+// Others.
+#[cfg(target_os = "android")]
+pub mod android;
+#[cfg(target_os = "dragonfly")]
+pub mod dragonfly;
+#[cfg(target_os = "emscripten")]
+pub mod emscripten;
+#[cfg(target_os = "espidf")]
+pub mod espidf;
+#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
+pub mod fortanix_sgx;
+#[cfg(target_os = "freebsd")]
+pub mod freebsd;
+#[cfg(target_os = "fuchsia")]
+pub mod fuchsia;
+#[cfg(target_os = "haiku")]
+pub mod haiku;
+#[cfg(target_os = "illumos")]
+pub mod illumos;
+#[cfg(target_os = "ios")]
+pub mod ios;
+#[cfg(target_os = "macos")]
+pub mod macos;
+#[cfg(target_os = "netbsd")]
+pub mod netbsd;
+#[cfg(target_os = "openbsd")]
+pub mod openbsd;
+#[cfg(target_os = "redox")]
+pub mod redox;
+#[cfg(target_os = "solaris")]
+pub mod solaris;
+
+#[cfg(target_os = "vxworks")]
+pub mod vxworks;
 
 #[cfg(any(unix, target_os = "wasi", doc))]
 mod fd;
index 8256b725acfa399877768d57c53b9b6c35915d4b..375d070516eb49bcbf7c1d047b107f6e817275da 100644 (file)
@@ -1,6 +1,6 @@
 Equivalent to C's `char` type.
 
-[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long.
+[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
 
 C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
 
index c29df6596fd946e45d567a5f3b7a1d11286db927..5b49f50763d74bba8e61ef66ad3097144325fbaa 100644 (file)
@@ -1,4 +1,4 @@
-//! Unix-specific extension to the primitives in the `std::ffi` module.
+//! Unix-specific extensions to primitives in the [`std::ffi`] module.
 //!
 //! # Examples
 //!
@@ -31,6 +31,8 @@
 //! let bytes = os_str.as_bytes();
 //! assert_eq!(bytes, b"foo");
 //! ```
+//!
+//! [`std::ffi`]: crate::ffi
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 6cf37f23c574d745d2c5fccb30f9dbd53a4f0e8f..0284a428b5d749b8695257d575592cd4f8298672 100644 (file)
@@ -1,10 +1,13 @@
-//! Unix-specific extensions to primitives in the `std::fs` module.
+//! Unix-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use super::platform::fs::MetadataExt as _;
 use crate::fs::{self, OpenOptions, Permissions};
 use crate::io;
+use crate::os::unix::io::{AsFd, AsRawFd};
 use crate::path::Path;
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner};
@@ -924,6 +927,75 @@ fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
     }
 }
 
+/// Change the owner and group of the specified path.
+///
+/// Specifying either the uid or gid as `None` will leave it unchanged.
+///
+/// Changing the owner typically requires privileges, such as root or a specific capability.
+/// Changing the group typically requires either being the owner and a member of the group, or
+/// having privileges.
+///
+/// If called on a symbolic link, this will change the owner and group of the link target. To
+/// change the owner and group of the link itself, see [`lchown`].
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+///     fs::chown("/sandbox", Some(0), Some(0))?;
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+    sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
+/// Change the owner and group of the file referenced by the specified open file descriptor.
+///
+/// For semantics and required privileges, see [`chown`].
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+///     let f = std::fs::File::open("/file")?;
+///     fs::fchown(f, Some(0), Some(0))?;
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+    sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
+/// Change the owner and group of the specified path, without dereferencing symbolic links.
+///
+/// Identical to [`chown`], except that if called on a symbolic link, this will change the owner
+/// and group of the link itself rather than the owner and group of the link target.
+///
+/// # Examples
+///
+/// ```no_run
+/// #![feature(unix_chown)]
+/// use std::os::unix::fs;
+///
+/// fn main() -> std::io::Result<()> {
+///     fs::lchown("/symlink", Some(0), Some(0))?;
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_chown", issue = "88989")]
+pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
+    sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
+}
+
 /// Change the root directory of the current process to the specified path.
 ///
 /// This typically requires privileges, such as root or a specific capability.
index 17a0259572446bf3337192ad10575279e1e2d4ee..62f750fa607c96fa5805ea9003a706edef301946 100644 (file)
@@ -4,8 +4,8 @@
 //! exposes Unix-specific functions that would otherwise be inappropriate as
 //! part of the core `std` library.
 //!
-//! It exposes more ways to deal with platform-specific strings (`OsStr`,
-//! `OsString`), allows to set permissions more granularly, extract low-level
+//! It exposes more ways to deal with platform-specific strings ([`OsStr`],
+//! [`OsString`]), allows to set permissions more granularly, extract low-level
 //! file descriptors from files and sockets, and has platform-specific helpers
 //! for spawning processes.
 //!
@@ -24,6 +24,9 @@
 //!     Ok(())
 //! }
 //! ```
+//!
+//! [`OsStr`]: crate::ffi::OsStr
+//! [`OsString`]: crate::ffi::OsString
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(cfg(unix))]
index d462bd4b5f75e8765e39424f19cb2d5555ef83cb..8ce8220885419d0877dd6bd96216f15c2e4c66fe 100644 (file)
@@ -1,4 +1,4 @@
-//! Unix-specific networking functionality
+//! Unix-specific networking functionality.
 
 #![stable(feature = "unix_socket", since = "1.10.0")]
 
index 650dcbabbae8c0beeb753bbad5b9fb7284b351b9..4d23805e479ba067e4eb5c00dabc13db24566a2a 100644 (file)
@@ -1,4 +1,6 @@
-//! Unix-specific extensions to primitives in the `std::process` module.
+//! Unix-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 7221da1a9a7bbc998b891b43bb8d7fbe82ed37f0..03dcc3a4f9ba0c24e48ec333bf7de381011de89d 100644 (file)
@@ -1,4 +1,6 @@
-//! Unix-specific extensions to primitives in the `std::thread` module.
+//! Unix-specific extensions to primitives in the [`std::thread`] module.
+//!
+//! [`std::thread`]: crate::thread
 
 #![stable(feature = "thread_extensions", since = "1.9.0")]
 
index 17e12a395a67047529abcaafb412c76fa556911c..41dd8702e98e9bc396c2ce8e8b8ba0f9aff757ca 100644 (file)
@@ -1,4 +1,6 @@
-//! WASI-specific extension to the primitives in the `std::ffi` module
+//! WASI-specific extensions to primitives in the [`std::ffi`] module
+//!
+//! [`std::ffi`]: crate::ffi
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 3df27563e21e9aafd5bc8f2eb0d0220f61faec12..907368061d7c430641a2f5e5cc8e6091f42a398c 100644 (file)
@@ -1,4 +1,6 @@
-//! WASI-specific extensions to primitives in the `std::fs` module.
+//! WASI-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
 
 #![deny(unsafe_op_in_unsafe_fn)]
 #![unstable(feature = "wasi_ext", issue = "71213")]
index d767c149dc5d08064f2e58cdec979ef80d1b8368..bbaf328f457e44ed98346e7c7ac18b73c3da8717 100644 (file)
@@ -24,6 +24,9 @@
 //!     Ok(())
 //! }
 //! ```
+//!
+//! [`OsStr`]: crate::ffi::OsStr
+//! [`OsString`]: crate::ffi::OsString
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
index 8d29fa7d66f995db0c4cdbd8142b0400516bb705..a9493a94cac26077427e221965ab736050df1635 100644 (file)
@@ -1,4 +1,4 @@
-//! Windows-specific extensions to the primitives in the `std::ffi` module.
+//! Windows-specific extensions to primitives in the [`std::ffi`] module.
 //!
 //! # Overview
 //!
@@ -49,6 +49,7 @@
 //! [ill-formed-utf-16]: https://simonsapin.github.io/wtf-8/#ill-formed-utf-16
 //! [`collect`]: crate::iter::Iterator::collect
 //! [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
+//! [`std::ffi`]: crate::ffi
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 71563a02dcbb931290b75a22c20ed4cc6bc1be80..be35ab0ca1e66cf62a34cedf54d90a7c99085a2d 100644 (file)
@@ -1,4 +1,6 @@
-//! Windows-specific extensions for the primitives in the `std::fs` module.
+//! Windows-specific extensions to primitives in the [`std::fs`] module.
+//!
+//! [`std::fs`]: crate::fs
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 969054dd3b3dcc8a72f37dbcf95a14e8de8369fd..52eb3b7c06769406a394b93d0a7dc27dbe10f29a 100644 (file)
@@ -5,6 +5,22 @@
 //! the core `std` library. These extensions allow developers to use
 //! `std` types and idioms with Windows in a way that the normal
 //! platform-agnostic idioms would not normally support.
+//!
+//! # Examples
+//!
+//! ```no_run
+//! use std::fs::File;
+//! use std::os::windows::prelude::*;
+//!
+//! fn main() -> std::io::Result<()> {
+//!     let f = File::create("foo.txt")?;
+//!     let handle = f.as_raw_handle();
+//!
+//!     // use handle with native windows bindings
+//!
+//!     Ok(())
+//! }
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(cfg(windows))]
index b246599dfc0a9d986c7f3f7b11e469c7b08965af..9510d104806db301e2892526faf67fead9561d68 100644 (file)
@@ -1,4 +1,6 @@
-//! Extensions to `std::process` for Windows.
+//! Windows-specific extensions to primitives in the [`std::process`] module.
+//!
+//! [`std::process`]: crate::process
 
 #![stable(feature = "process_extensions", since = "1.2.0")]
 
index fb1bf66ceed356aa1da457a24d3f3171dcda9d1a..d81d6d0ac28a9dfada48c7ee9e17a5184011d41f 100644 (file)
@@ -1,4 +1,6 @@
-//! Extensions to `std::thread` for Windows.
+//! Windows-specific extensions to primitives in the [`std::thread`] module.
+//!
+//! [`std::thread`]: crate::thread
 
 #![stable(feature = "thread_extensions", since = "1.9.0")]
 
index c1c039584979d3817f876da3929daf69d1fb0433..21e9669c11079718073c402f8d4135859e7ec7f2 100644 (file)
@@ -10,7 +10,7 @@
 
 #[doc(hidden)]
 #[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
-#[allow_internal_unstable(libstd_sys_internals, const_format_args)]
+#[allow_internal_unstable(libstd_sys_internals, const_format_args, core_panic)]
 #[cfg_attr(not(test), rustc_diagnostic_item = "std_panic_2015_macro")]
 #[rustc_macro_transparency = "semitransparent"]
 pub macro panic_2015 {
     ($msg:expr $(,)?) => ({
         $crate::rt::begin_panic($msg)
     }),
+    // Special-case the single-argument case for const_panic.
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::rt::panic_display(&$arg)
+    }),
     ($fmt:expr, $($arg:tt)+) => ({
         $crate::rt::begin_panic_fmt(&$crate::const_format_args!($fmt, $($arg)+))
     }),
index b0ebfe648a5234a8caf184d7ae90ef4fa87ac59f..0de9126dab2fe5679ea2390903a0c1e3293e59a4 100644 (file)
@@ -1,3 +1,6 @@
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
 #[doc(primitive = "bool")]
 #[doc(alias = "true")]
 #[doc(alias = "false")]
 /// assert!(!bool_val);
 /// ```
 ///
-/// [`true`]: keyword.true.html
-/// [`false`]: keyword.false.html
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
 /// [`BitAnd`]: ops::BitAnd
 /// [`BitOr`]: ops::BitOr
 /// [`Not`]: ops::Not
-/// [`if`]: keyword.if.html
+/// [`if`]: ../std/keyword.if.html
 ///
 /// # Examples
 ///
@@ -103,7 +106,7 @@ mod prim_bool {}
 /// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
 ///
 /// [`u32`]: prim@u32
-/// [`exit`]: process::exit
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
 ///
 /// # `!` and generics
 ///
@@ -188,7 +191,7 @@ mod prim_bool {}
 /// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str::FromStr::from_str
-/// [`String`]: string::String
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
 /// [`FromStr`]: str::FromStr
 ///
 /// # `!` and traits
@@ -264,7 +267,7 @@ mod prim_bool {}
 /// `impl` for this which simply panics, but the same is true for any type (we could `impl
 /// Default` for (eg.) [`File`] by just making [`default()`] panic.)
 ///
-/// [`File`]: fs::File
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
 /// [`Debug`]: fmt::Debug
 /// [`default()`]: Default::default
 ///
@@ -272,7 +275,6 @@ mod prim_bool {}
 mod prim_never {}
 
 #[doc(primitive = "char")]
-//
 /// A character type.
 ///
 /// The `char` type represents a single character. More specifically, since
@@ -304,7 +306,7 @@ mod prim_never {}
 /// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
 /// ```
 ///
-/// [`String`]: string/struct.String.html
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
 ///
 /// As always, remember that a human intuition for 'character' might not map to
 /// Unicode's definitions. For example, despite looking similar, the 'é'
@@ -499,7 +501,7 @@ mod prim_unit {}
 /// [`null_mut`]: ptr::null_mut
 /// [`is_null`]: pointer::is_null
 /// [`offset`]: pointer::offset
-/// [`into_raw`]: Box::into_raw
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
 /// [`drop`]: mem::drop
 /// [`write`]: ptr::write
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -581,9 +583,9 @@ 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](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
+/// `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
@@ -1042,15 +1044,15 @@ 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`](keyword.ref.html) or
-/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
+/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/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,
 /// <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.
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/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.
 ///
@@ -1117,6 +1119,7 @@ mod prim_usize {}
 ///
 /// [`DerefMut`]: ops::DerefMut
 /// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
 ///
 /// The following traits are implemented on `&T` references if the underlying `T` also implements
 /// that trait:
@@ -1134,7 +1137,7 @@ mod prim_usize {}
 /// [`std::fmt`]: fmt
 /// ['Pointer`]: fmt::Pointer
 /// [`Hash`]: hash::Hash
-/// [`ToSocketAddrs`]: net::ToSocketAddrs
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
 ///
 /// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
 /// implements that trait:
@@ -1155,9 +1158,10 @@ mod prim_usize {}
 ///
 /// [`FusedIterator`]: iter::FusedIterator
 /// [`TrustedLen`]: iter::TrustedLen
-/// [`Seek`]: io::Seek
-/// [`BufRead`]: io::BufRead
-/// [`Read`]: io::Read
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
 ///
 /// Note that due to method call deref coercion, simply calling a trait method will act like they
 /// work on references as well as they do on owned values! The implementations described here are
index 72e6c23ee49907a5b1b760577518ead2d7680ffb..893167e373015ca84c7a7ec242be6c85878991aa 100644 (file)
@@ -16,6 +16,7 @@
 
 // Re-export some of our utilities which are expected by other crates.
 pub use crate::panicking::{begin_panic, begin_panic_fmt, panic_count};
+pub use core::panicking::panic_display;
 
 // To reduce the generated code of the new `lang_start`, this function is doing
 // the real work.
@@ -59,10 +60,10 @@ fn lang_start<T: crate::process::Termination + 'static>(
     argc: isize,
     argv: *const *const u8,
 ) -> isize {
-    lang_start_internal(
+    let Ok(v) = lang_start_internal(
         &move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report(),
         argc,
         argv,
-    )
-    .into_ok()
+    );
+    v
 }
index 6d7524a733afd85cac14a01793ee06047328f5fc..a4fff9b2e64731c7f775fcff82075bbf3b2c3784 100644 (file)
@@ -1416,6 +1416,23 @@ fn fclonefileat(
     Ok(bytes_copied as u64)
 }
 
+pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
+    let path = cstr(path)?;
+    cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
+    Ok(())
+}
+
+pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
+    cvt(unsafe { libc::fchown(fd, uid as libc::uid_t, gid as libc::gid_t) })?;
+    Ok(())
+}
+
+pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
+    let path = cstr(path)?;
+    cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
+    Ok(())
+}
+
 #[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
 pub fn chroot(dir: &Path) -> io::Result<()> {
     let dir = cstr(dir)?;
index e9207ee36171b18d44613c17583cf0a77f0232e0..bf3eb5b30c77d356d9b1d256b25c9ae1f22c05ba 100644 (file)
@@ -44,6 +44,9 @@
 #[stable(feature = "time", since = "1.3.0")]
 pub use core::time::Duration;
 
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+pub use core::time::FromSecsError;
+
 /// A measurement of a monotonically nondecreasing clock.
 /// Opaque and useful only with [`Duration`].
 ///
index fa96b7abff6d61aa0920c52398e1d52c29e8b903..198ae739b55674d990396cfe6128a45c807dc3a9 100644 (file)
@@ -37,35 +37,36 @@ pub(in crate::time) fn monotonize_impl(mono: &AtomicU64, raw: time::Instant) ->
         // This could be a problem for programs that call instants at intervals greater
         // than 68 years. Interstellar probes may want to ensure that actually_monotonic() is true.
         let packed = (secs << 32) | nanos;
-        let old = mono.load(Relaxed);
-
-        if old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2 {
-            mono.store(packed, Relaxed);
-            raw
-        } else {
-            // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
-            // passed in value and the 64bits loaded from the atomic
-            let seconds_lower = old >> 32;
-            let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
-            if secs & 0xffff_ffff > seconds_lower {
-                // Backslide caused the lower 32bit of the seconds part to wrap.
-                // This must be the case because the seconds part is larger even though
-                // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
-                //
-                // We assume that backslides are smaller than 2^32 seconds
-                // which means we need to add 1 to the upper half to restore it.
-                //
-                // Example:
-                // most recent observed time: 0xA1_0000_0000_0000_0000u128
-                // bits stored in AtomicU64:     0x0000_0000_0000_0000u64
-                // backslide by 1s
-                // caller time is             0xA0_ffff_ffff_0000_0000u128
-                // -> we can fix up the upper half time by adding 1 << 32
-                seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
+        let updated = mono.fetch_update(Relaxed, Relaxed, |old| {
+            (old == UNINITIALIZED || packed.wrapping_sub(old) < u64::MAX / 2).then_some(packed)
+        });
+        match updated {
+            Ok(_) => raw,
+            Err(newer) => {
+                // Backslide occurred. We reconstruct monotonized time from the upper 32 bit of the
+                // passed in value and the 64bits loaded from the atomic
+                let seconds_lower = newer >> 32;
+                let mut seconds_upper = secs & 0xffff_ffff_0000_0000;
+                if secs & 0xffff_ffff > seconds_lower {
+                    // Backslide caused the lower 32bit of the seconds part to wrap.
+                    // This must be the case because the seconds part is larger even though
+                    // we are in the backslide branch, i.e. the seconds count should be smaller or equal.
+                    //
+                    // We assume that backslides are smaller than 2^32 seconds
+                    // which means we need to add 1 to the upper half to restore it.
+                    //
+                    // Example:
+                    // most recent observed time: 0xA1_0000_0000_0000_0000u128
+                    // bits stored in AtomicU64:     0x0000_0000_0000_0000u64
+                    // backslide by 1s
+                    // caller time is             0xA0_ffff_ffff_0000_0000u128
+                    // -> we can fix up the upper half time by adding 1 << 32
+                    seconds_upper = seconds_upper.wrapping_add(0x1_0000_0000);
+                }
+                let secs = seconds_upper | seconds_lower;
+                let nanos = newer as u32;
+                ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
             }
-            let secs = seconds_upper | seconds_lower;
-            let nanos = old as u32;
-            ZERO.checked_add_duration(&Duration::new(secs, nanos)).unwrap()
         }
     }
 }
index c4b0e1e5c23392f00a4eaada6a288fb53a03df11..aa2448075141935819b27a6f4bfc69a12083c063 100644 (file)
@@ -53,7 +53,7 @@ fn write_result(
         // Because the testsuit node holds some of the information as attributes, we can't write it
         // until all of the tests has ran. Instead of writting every result as they come in, we add
         // them to a Vec and write them all at once when run is complete.
-        let duration = exec_time.map(|t| t.0.clone()).unwrap_or_default();
+        let duration = exec_time.map(|t| t.0).unwrap_or_default();
         self.results.push((desc.clone(), result.clone(), duration));
         Ok(())
     }
index f4c5a05d1e2cebbd97f717274c5d40c434887b78..694473f52c1a79970e86b1888b737e305db37041 100644 (file)
@@ -16,6 +16,7 @@
 use searcher::get_dbpath_for_term;
 
 /// A parsed terminfo database entry.
+#[allow(unused)]
 #[derive(Debug)]
 pub(crate) struct TermInfo {
     /// Names for the terminal
index 0b76a13e02b7774334b87bf1dd83a3f5728f381c..1ce1f0b26db58030254cf0a903fa10d751476da3 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "bootstrap"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 build = "build.rs"
 
 [lib]
index 1f1eca1c76cf101ccded1b19843cef64a855bfd1..57ade88f733062ebd1667e9197e2de1b195ce35f 100644 (file)
@@ -277,6 +277,7 @@ def default_build_triple(verbose):
         'i486': 'i686',
         'i686': 'i686',
         'i786': 'i686',
+        'm68k': 'm68k',
         'powerpc': 'powerpc',
         'powerpc64': 'powerpc64',
         'powerpc64le': 'powerpc64le',
index f5fad4b4136849c8f023eda32bb9d71365f7e1b1..f66f282bea933e0bfbf817f589e74c814eb3fd16 100644 (file)
@@ -262,7 +262,7 @@ fn run(self, builder: &Builder<'_>) {
         let mut cargo = builder.cargo(
             compiler,
             Mode::Codegen,
-            SourceType::Submodule,
+            SourceType::InTree,
             target,
             cargo_subcommand(builder.kind),
         );
index df9e9bce415276245571bf083e0608ee390e1d88..ae234fb1dc729ba9cef9b98992c44dbd88252b99 100644 (file)
@@ -817,8 +817,7 @@ fn run(self, builder: &Builder<'_>) {
 
         let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
 
-        let mut cargo =
-            builder.cargo(compiler, Mode::Codegen, SourceType::Submodule, target, "build");
+        let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build");
         cargo
             .arg("--manifest-path")
             .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
index c871411793073ee3c50f7fe0c42311510cbdfc27..af3774b7c7586ef3f33d38747405153b0eb4dff0 100644 (file)
@@ -537,7 +537,7 @@ impl Step for Rustc {
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         let builder = run.builder;
-        run.krate("rustc-main").default_condition(builder.config.docs)
+        run.krate("rustc-main").path("compiler").default_condition(builder.config.docs)
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -553,9 +553,24 @@ fn make_run(run: RunConfig<'_>) {
     fn run(self, builder: &Builder<'_>) {
         let stage = self.stage;
         let target = self.target;
+        let mut is_explicit_request = false;
         builder.info(&format!("Documenting stage{} compiler ({})", stage, target));
 
-        if !builder.config.compiler_docs {
+        let paths = builder
+            .paths
+            .iter()
+            .map(components_simplified)
+            .filter_map(|path| {
+                if path.get(0) == Some(&"compiler") {
+                    is_explicit_request = true;
+                    path.get(1).map(|p| p.to_owned())
+                } else {
+                    None
+                }
+            })
+            .collect::<Vec<_>>();
+
+        if !builder.config.compiler_docs && !is_explicit_request {
             builder.info("\tskipping - compiler/librustdoc docs disabled");
             return;
         }
@@ -589,32 +604,69 @@ fn run(self, builder: &Builder<'_>) {
         cargo.rustdocflag("-Zunstable-options");
         cargo.rustdocflag("-Znormalize-docs");
         cargo.rustdocflag("--show-type-layout");
+        cargo.rustdocflag("--generate-link-to-definition");
         compile::rustc_cargo(builder, &mut cargo, target);
+        cargo.arg("-Zunstable-options");
         cargo.arg("-Zskip-rustdoc-fingerprint");
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
+        // Do link to dependencies on `docs.rs` however using `rustdoc-map`.
         cargo.arg("--no-deps");
+        cargo.arg("-Zrustdoc-map");
+
+        // FIXME: `-Zrustdoc-map` does not yet correctly work for transitive dependencies,
+        // once this is no longer an issue the special case for `ena` can be removed.
+        cargo.rustdocflag("--extern-html-root-url");
+        cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
 
-        // Find dependencies for top level crates.
         let mut compiler_crates = HashSet::new();
-        for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] {
-            compiler_crates.extend(
-                builder
-                    .in_tree_crates(root_crate, Some(target))
-                    .into_iter()
-                    .map(|krate| krate.name),
-            );
+
+        if paths.is_empty() {
+            // Find dependencies for top level crates.
+            for root_crate in &["rustc_driver", "rustc_codegen_llvm", "rustc_codegen_ssa"] {
+                compiler_crates.extend(
+                    builder
+                        .in_tree_crates(root_crate, Some(target))
+                        .into_iter()
+                        .map(|krate| krate.name),
+                );
+            }
+        } else {
+            for root_crate in paths {
+                if !builder.src.join("compiler").join(&root_crate).exists() {
+                    builder.info(&format!(
+                        "\tskipping - compiler/{} (unknown compiler crate)",
+                        root_crate
+                    ));
+                } else {
+                    compiler_crates.extend(
+                        builder
+                            .in_tree_crates(root_crate, Some(target))
+                            .into_iter()
+                            .map(|krate| krate.name),
+                    );
+                }
+            }
         }
 
+        let mut to_open = None;
         for krate in &compiler_crates {
             // Create all crate output directories first to make sure rustdoc uses
             // relative links.
             // FIXME: Cargo should probably do this itself.
             t!(fs::create_dir_all(out_dir.join(krate)));
             cargo.arg("-p").arg(krate);
+            if to_open.is_none() {
+                to_open = Some(krate);
+            }
         }
 
         builder.run(&mut cargo.into());
+        // Let's open the first crate documentation page:
+        if let Some(krate) = to_open {
+            let index = out.join(krate).join("index.html");
+            open(builder, &index);
+        }
     }
 }
 
index a4735d54be03828f1d91c37a3c507c85f4cefc00..2d4e15278972469bacd9de44c1b11b34fcaf39f5 100644 (file)
@@ -1494,8 +1494,13 @@ fn ninja(&self) -> bool {
             {
                 eprintln!(
                     "
-Couldn't find required command: ninja
-You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
+Couldn't find required command: ninja (or ninja-build)
+
+You should install ninja as described at
+<https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages>,
+or set `ninja = false` in the `[llvm]` section of `config.toml`.
+Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
+to download LLVM rather than building it.
 "
                 );
                 std::process::exit(1);
index 0e306cb7211b5e9a186ed0b4d3871572469ba9c2..27c9bb2504f6d2bdb030f5ee7725ad63f4a783b6 100644 (file)
@@ -165,7 +165,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
 
         let llvm_exp_targets = match builder.config.llvm_experimental_targets {
             Some(ref s) => s,
-            None => "AVR",
+            None => "AVR;M68k",
         };
 
         let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
index d12e86b7c1deb1832e71510d1a5b6fd73059c666..272b7153111370a1a341474b84f971857fc096e4 100644 (file)
@@ -390,7 +390,7 @@ fn run(self, builder: &Builder<'_>) {
             host,
             "test",
             "src/tools/rustfmt",
-            SourceType::Submodule,
+            SourceType::InTree,
             &[],
         );
 
@@ -925,6 +925,11 @@ fn run(self, builder: &Builder<'_>) {
                     .env("RUSTDOC", builder.rustdoc(self.compiler))
                     .env("RUSTC", builder.rustc(self.compiler))
                     .current_dir(path);
+                // FIXME: implement a `// compile-flags` command or similar
+                //        instead of hard-coding this test
+                if entry.file_name() == "link_to_definition" {
+                    cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
+                }
                 builder.run(&mut cargo);
             }
         }
index 17a9e55b3238cd0345b00012b3c1c3bbe1fede82..d88df0e08fab3e01ef9b596bcf58629a01710301 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "build_helper"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 path = "lib.rs"
diff --git a/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-m68k-linux/Dockerfile
new file mode 100644 (file)
index 0000000..1720399
--- /dev/null
@@ -0,0 +1,26 @@
+FROM ubuntu:20.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils \
+  g++-m68k-linux-gnu \
+  libssl-dev \
+  pkg-config
+
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV HOSTS=m68k-unknown-linux-gnu
+
+ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
index 6417f5a984ad55070e00731831ef815bd472998c..c9f8692d41887e1546d32836cece40f546f421cf 100644 (file)
@@ -635,6 +635,9 @@ jobs:
               SCRIPT: python x.py dist
               # RLS does not build for aarch64-pc-windows-msvc. See rust-lang/rls#1693
               DIST_REQUIRE_ALL_TOOLS: 0
+              # Hack around this SDK version, because it doesn't work with clang.
+              # See https://github.com/rust-lang/rust/issues/88796
+              WINDOWS_SDK_20348_HACK: 1
             <<: *job-windows-xl
 
           - name: dist-i686-mingw
index 7b540b5c6e99dd2bc0f274df220bef1fb13f983a..fd29d3a022ad3860be66cbb67bf69415daee65a7 100755 (executable)
@@ -37,6 +37,12 @@ if isMacOS; then
     # `clang-ar` by accident.
     ciCommandSetEnv AR "ar"
 elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
+
+    if [[ ${WINDOWS_SDK_20348_HACK-0} -eq 1 ]]; then
+        rm -rf '/c/Program Files (x86)/Windows Kits/10/include/10.0.20348.0'
+        mv '/c/Program Files (x86)/Windows Kits/10/include/'10.0.{19041,20348}.0
+    fi
+
     # If we're compiling for MSVC then we, like most other distribution builders,
     # switch to clang as the compiler. This'll allow us eventually to enable LTO
     # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
index 1023e4b0e2837d2ef4b2a7b4f07fb01cff29a2fc..d3da6d1ac915a3a24dd5ca14f0ef582c20042c8b 100755 (executable)
@@ -18,14 +18,6 @@ verify_backported_commits_main() {
     exit 0
   fi
 
-  echo 'git: unshallowing the repository so we can check commits'
-  git fetch \
-    --no-tags \
-    --no-recurse-submodules \
-    --progress \
-    --prune \
-    --unshallow
-
   if [[ $ci_base_branch == "beta" ]]; then
     verify_cherries master "$BETA_LIMIT" \
       || exit 1
index c3a51e23859554369e6bbb5128dcef0e4f159fb5..4c76da9ddb4650203c129fceffdea95a3466c205 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c3a51e23859554369e6bbb5128dcef0e4f159fb5
+Subproject commit 4c76da9ddb4650203c129fceffdea95a3466c205
index 04f489c889235fe3b6dfe678ae5410d07deda958..9d4132b56c4999cd3ce1aeca5f1b2f2cb0d11c24 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 04f489c889235fe3b6dfe678ae5410d07deda958
+Subproject commit 9d4132b56c4999cd3ce1aeca5f1b2f2cb0d11c24
index 95f1acf9a39d6f402f654e917e2c1dfdb779c5fc..9198465b6ca8bed669df0cbb67c0e6d0b140803c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 95f1acf9a39d6f402f654e917e2c1dfdb779c5fc
+Subproject commit 9198465b6ca8bed669df0cbb67c0e6d0b140803c
index 6da0703beacc98d394f5af29b98abad5f5ecb6b1..0f106292e96700edc113db4c114965fb9540e231 100644 (file)
@@ -217,6 +217,7 @@ target | std | host | notes
 `armv5te-unknown-linux-uclibceabi` | ? |  | ARMv5TE Linux with uClibc
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
 `armv6-unknown-netbsd-eabihf` | ? |  |
+`armv6k-nintendo-3ds` | * |  | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
 `armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
@@ -237,6 +238,7 @@ target | std | host | notes
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
+`m68k-unknown-linux-gnu` | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 `mipsel-sony-psp` | * |  | MIPS (LE) Sony PlayStation Portable (PSP)
 `mipsel-unknown-linux-uclibc` | ✓ |  | MIPS (LE) Linux with uClibc
diff --git a/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/m68k-unknown-linux-gnu.md
new file mode 100644 (file)
index 0000000..d325ba3
--- /dev/null
@@ -0,0 +1,97 @@
+# m68k-unknown-linux-gnu
+
+**Tier: 3**
+
+Motorola 680x0 Linux
+
+## Designated Developers
+
+* [@glaubitz](https://github.com/glaubitz)
+* [@ricky26](https://github.com/ricky26)
+
+## Requirements
+
+This target requires a Linux/m68k build environment for cross-compilation which
+is available on Debian and Debian-based systems, openSUSE and other distributions.
+
+On Debian, it should be sufficient to install a g++ cross-compiler for the m68k
+architecture which will automatically pull in additional dependencies such as
+the glibc cross development package:
+
+```text
+# apt install g++-m68k-linux-gnu
+```
+
+Binaries can be run using QEMU user emulation. On Debian-based systems, it should be
+sufficient to install the package `qemu-user-static` to be able to run simple static
+binaries:
+
+```text
+# apt install qemu-user-static
+```
+
+To run more complex programs, it will be necessary to set up a Debian/m68k chroot with
+the help of the command `debootstrap`:
+
+```text
+# apt install debootstrap debian-ports-archive-keyring
+# debootstrap --keyring=/usr/share/keyrings/debian-ports-archive-keyring.gpg --arch=m68k unstable debian-68k http://ftp.ports.debian.org/debian-ports
+```
+
+This chroot can then seamlessly entered using the normal `chroot` command thanks to
+QEMU user emulation:
+
+```text
+# chroot /path/to/debian-68k
+```
+
+To get started with native builds, which are currently untested, a native Debian/m68k
+system can be installed either on real hardware such as 68k-based Commodore Amiga or
+Atari systems or emulated environments such as QEMU version 4.2 or newer or ARAnyM.
+
+ISO images for installation are provided by the Debian Ports team and can be obtained
+from the Debian CD image server available at:
+
+[https://cdimage.debian.org/cdimage/ports/current](https://cdimage.debian.org/cdimage/ports/current/)
+
+Documentation for Debian/m68k is available on the Debian Wiki at:
+
+[https://wiki.debian.org/M68k](https://wiki.debian.org/M68k)
+
+Support is available either through the `debian-68k` mailing list:
+
+[https://lists.debian.org/debian-68k/](https://lists.debian.org/debian-68k/)
+
+or the `#debian-68k` IRC channel on OFTC network.
+
+## Building
+
+The codegen for this target should be built by default. However, core and std
+are currently missing but are being worked on and should become available in
+the near future.
+
+## Cross-compilation
+
+This target can be cross-compiled from a standard Debian or Debian-based, openSUSE or any
+other distribution which has a basic m68k cross-toolchain available.
+
+## Testing
+
+Currently there is no support to run the rustc test suite for this target.
+
+## Building Rust programs
+
+Rust programs can be built for that target:
+
+```text
+rustc --target m68k-unknown-linux-gnu your-code.rs
+```
+
+Very simple progams can be run using the `qemu-m68k-static` program:
+
+```text
+$ qemu-m68k-static your-code
+```
+
+For more complex applications, a chroot or native (emulated) Debian/m68k system are required
+for testing.
index dce98abcf53d7a57e68b7e2b531616e2d4576bb3..b55db452f124c52708d94cdbafb1789d538aa80f 100644 (file)
@@ -222,13 +222,13 @@ all these files are linked from every page, changing where they are can be cumbe
 specially cache them. This flag will rename all these files in the output to include the suffix in
 the filename. For example, `light.css` would become `light-suf.css` with the above command.
 
-### `--display-warnings`: display warnings when documenting or running documentation tests
+### `--display-doctest-warnings`: display warnings when documenting or running documentation tests
 
 Using this flag looks like this:
 
 ```bash
-$ rustdoc src/lib.rs -Z unstable-options --display-warnings
-$ rustdoc --test src/lib.rs -Z unstable-options --display-warnings
+$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings
+$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings
 ```
 
 The intent behind this flag is to allow the user to see warnings that occur within their library or
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
new file mode 100644 (file)
index 0000000..977d258
--- /dev/null
@@ -0,0 +1,24 @@
+# `remap-cwd-prefix`
+
+The tracking issue for this feature is: [#87325](https://github.com/rust-lang/rust/issues/87325).
+
+------------------------
+
+This flag will rewrite absolute paths under the current working directory,
+replacing the current working directory prefix with a specified value.
+
+The given value may be absolute or relative, or empty. This switch takes
+precidence over `--remap-path-prefix` in case they would both match a given
+path.
+
+This flag helps to produce deterministic output, by removing the current working
+directory from build output, while allowing the command line to be universally
+reproducible, such that the same execution will work on all machines, regardless
+of build environment.
+
+## Example
+```sh
+# This would produce an absolute path to main.rs in build outputs of
+# "./main.rs".
+rustc -Z remap-cwd-prefix=. main.rs
+```
index a10928a7471770ae520ba86dd2a8396096cce420..ccaf6e8733e0c2e2987f8f58b7f2eb23fad3f23e 100644 (file)
@@ -375,7 +375,7 @@ Any reuse of a named label, local or otherwise, can result in a assembler or lin
 
 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.
+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 `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
 
 ```rust,allow_fail
 #![feature(asm)]
@@ -804,9 +804,9 @@ The following ABIs can be used with `clobber_abi`:
 
 | Architecture | ABI name | Clobbered registers |
 | ------------ | -------- | ------------------- |
-| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
+| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
 | AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` |
 | ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` |
 | RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` |
index 8226e815c2c1e846f4dec07d07943076abc4e8e1..7ee19a0b6d91397540034fd1bea8a614435cacd6 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "test-float-parse"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 publish = false
 
 [workspace]
index e02cef235ae00331c5d3aa0ab6b70f6b2df0efb8..945b2a8e9a80e75c8f011041f45f20264ce46a9a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 path = "lib.rs"
index ff3641d6c9ab05adcf61bdca2a83228f468ef8d9..15d4563ad7461b7d083439bb726cd3a8b0289129 100644 (file)
@@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
         let param_env = self.cx.tcx.param_env(item_def_id);
         let ty = self.cx.tcx.type_of(item_def_id);
 
-        debug!("get_blanket_impls({:?})", ty);
+        trace!("get_blanket_impls({:?})", ty);
         let mut impls = Vec::new();
         for &trait_def_id in self.cx.tcx.all_traits(()).iter() {
             if !self.cx.cache.access_levels.is_public(trait_def_id)
@@ -28,9 +28,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
             // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
             let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id);
             for &impl_def_id in trait_impls.blanket_impls() {
-                debug!(
+                trace!(
                     "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
-                    trait_def_id, impl_def_id
+                    trait_def_id,
+                    impl_def_id
                 );
                 let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_));
@@ -50,9 +51,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         // FIXME(eddyb) ignoring `obligations` might cause false positives.
                         drop(obligations);
 
-                        debug!(
+                        trace!(
                             "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
-                            param_env, trait_ref, ty
+                            param_env,
+                            trait_ref,
+                            ty
                         );
                         let predicates = self
                             .cx
index 592aefb6a4b015a044e7605e7f8b422c0116059d..9b5ca06848646fcc929fef25ec9046fc2de053f8 100644 (file)
@@ -491,6 +491,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
                         "aarch64" => "AArch64",
                         "arm" => "ARM",
                         "asmjs" => "JavaScript",
+                        "m68k" => "M68k",
                         "mips" => "MIPS",
                         "mips64" => "MIPS-64",
                         "msp430" => "MSP430",
index 0c81a5584301355e4d70e84c4b8139751c0d5b6b..29834c82b3de32a20d02e3a54aeec942089ddc50 100644 (file)
@@ -447,9 +447,9 @@ fn merge_attrs(
     }
 
     let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
-    debug!("merged_attrs={:?}", merged_attrs);
+    trace!("merged_attrs={:?}", merged_attrs);
 
-    debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
+    trace!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
     ret.push(clean::Item::from_def_id_and_attrs_and_parts(
         did,
         None,
@@ -482,12 +482,13 @@ fn build_module(
     // visit each node at most once.
     for &item in cx.tcx.item_children(did).iter() {
         if item.vis == ty::Visibility::Public {
-            if let Some(def_id) = item.res.mod_def_id() {
+            let res = item.res.expect_non_local();
+            if let Some(def_id) = res.mod_def_id() {
                 if did == def_id || !visited.insert(def_id) {
                     continue;
                 }
             }
-            if let Res::PrimTy(p) = item.res {
+            if let Res::PrimTy(p) = res {
                 // Primitive types can't be inlined so generate an import instead.
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
@@ -500,7 +501,7 @@ fn build_module(
                         clean::ImportSource {
                             path: clean::Path {
                                 global: false,
-                                res: item.res,
+                                res,
                                 segments: vec![clean::PathSegment {
                                     name: prim_ty.as_sym(),
                                     args: clean::GenericArgs::AngleBracketed {
@@ -515,9 +516,7 @@ fn build_module(
                     ))),
                     cfg: None,
                 });
-            } else if let Some(i) =
-                try_inline(cx, did, None, item.res, item.ident.name, None, visited)
-            {
+            } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
                 items.extend(i)
             }
         }
@@ -557,7 +556,6 @@ fn build_macro(
     name: Symbol,
     import_def_id: Option<DefId>,
 ) -> clean::ItemKind {
-    let imported_from = cx.tcx.crate_name(def_id.krate);
     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 {
@@ -569,7 +567,6 @@ fn build_macro(
                         def_id,
                         cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
                     ),
-                    imported_from: Some(imported_from),
                 })
             } else {
                 unreachable!()
index e2ad21bba21b754400031c8bc6283494d0f974e9..e281bbc59c255c26e0b707e225d6356e5e60e6df 100644 (file)
@@ -164,14 +164,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
             );
         }
         inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-        let path = external_path(
-            cx,
-            cx.tcx.item_name(trait_ref.def_id),
-            Some(trait_ref.def_id),
-            true,
-            bounds.to_vec(),
-            trait_ref.substs,
-        );
+        let path = external_path(cx, trait_ref.def_id, true, bounds.to_vec(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
 
@@ -906,7 +899,7 @@ fn clean(&self, _: &mut DocContext<'_>) -> bool {
 impl Clean<Type> for hir::TraitRef<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let path = self.path.clean(cx);
-        resolve_type(cx, path, self.hir_ref_id)
+        resolve_type(cx, path)
     }
 }
 
@@ -1164,7 +1157,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Item {
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     use rustc_hir::GenericParamCount;
-    let hir::Ty { hir_id, span, ref kind } = *hir_ty;
+    let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
         _ => unreachable!(),
@@ -1271,7 +1264,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
             }
             let path = path.clean(cx);
-            resolve_type(cx, path, hir_id)
+            resolve_type(cx, path)
         }
         hir::QPath::Resolved(Some(ref qself), ref p) => {
             // Try to normalize `<X as Y>::T` to a type
@@ -1292,7 +1285,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 name: p.segments.last().expect("segments were empty").ident.name,
                 self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
                 self_type: Box::new(qself.clean(cx)),
-                trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+                trait_: Box::new(resolve_type(cx, trait_path)),
             }
         }
         hir::QPath::TypeRelative(ref qself, ref segment) => {
@@ -1308,7 +1301,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 name: segment.ident.name,
                 self_def_id: res.opt_def_id(),
                 self_type: Box::new(qself.clean(cx)),
-                trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+                trait_: Box::new(resolve_type(cx, trait_path)),
             }
         }
         hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
@@ -1406,7 +1399,7 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
 
 impl<'tcx> Clean<Type> for Ty<'tcx> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
-        debug!("cleaning type: {:?}", self);
+        trace!("cleaning type: {:?}", self);
         let ty = normalize(cx, self).unwrap_or(self);
         match *ty.kind() {
             ty::Never => Never,
@@ -1448,19 +1441,12 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                     AdtKind::Enum => ItemType::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
+                let path = external_path(cx, did, false, vec![], substs);
                 ResolvedPath { path, did, is_generic: false }
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-                let path = external_path(
-                    cx,
-                    cx.tcx.item_name(did),
-                    None,
-                    false,
-                    vec![],
-                    InternalSubsts::empty(),
-                );
+                let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
                 ResolvedPath { path, did, is_generic: false }
             }
             ty::Dynamic(ref obj, ref reg) => {
@@ -1484,8 +1470,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
 
                 for did in dids {
                     let empty = cx.tcx.intern_substs(&[]);
-                    let path =
-                        external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+                    let path = external_path(cx, did, false, vec![], empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     let bound = PolyTrait {
                         trait_: ResolvedPath { path, did, is_generic: false },
@@ -1502,8 +1487,7 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Type {
                     });
                 }
 
-                let path =
-                    external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
+                let path = external_path(cx, did, false, bindings, substs);
                 bounds.insert(
                     0,
                     PolyTrait {
@@ -1859,7 +1843,6 @@ fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
                 }
                 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
index 5eff56a2200e10d396cfc9eba35c29b37b486859..b3c320555f9e53e08e030134b440432ed4722cab 100644 (file)
@@ -212,7 +212,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
     crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
         let root = self.def_id();
 
-        let as_keyword = |res: Res| {
+        let as_keyword = |res: Res<!>| {
             if let Res::Def(DefKind::Mod, def_id) = res {
                 let attrs = tcx.get_attrs(def_id);
                 let mut keyword = None;
@@ -243,7 +243,8 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
+                            as_keyword(path.res.expect_non_local())
+                                .map(|(_, prim)| (id.def_id.to_def_id(), prim))
                         }
                         _ => None,
                     }
@@ -274,7 +275,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
         // Also note that this does not attempt to deal with modules tagged
         // duplicately for the same primitive. This is handled later on when
         // rendering by delegating everything to a hash map.
-        let as_primitive = |res: Res| {
+        let as_primitive = |res: Res<!>| {
             if let Res::Def(DefKind::Mod, def_id) = res {
                 let attrs = tcx.get_attrs(def_id);
                 let mut prim = None;
@@ -309,7 +310,7 @@ fn to_remote(url: impl ToString) -> ExternalLocation {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_primitive(path.res).map(|(_, prim)| {
+                            as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
                                 // Pretend the primitive is local.
                                 (id.def_id.to_def_id(), prim)
                             })
@@ -461,60 +462,20 @@ pub fn from_def_id_and_attrs_and_parts(
             .map_or(&[][..], |v| v.as_slice())
             .iter()
             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
-                match did {
-                    Some(did) => {
-                        if let Ok((mut href, ..)) = href(did.clone(), cx) {
-                            if let Some(ref fragment) = *fragment {
-                                href.push('#');
-                                href.push_str(fragment);
-                            }
-                            Some(RenderedLink {
-                                original_text: s.clone(),
-                                new_text: link_text.clone(),
-                                href,
-                            })
-                        } else {
-                            None
-                        }
-                    }
-                    // FIXME(83083): using fragments as a side-channel for
-                    // primitive names is very unfortunate
-                    None => {
-                        let relative_to = &cx.current;
-                        if let Some(ref fragment) = *fragment {
-                            let url = match cx.cache().extern_locations.get(&self.def_id.krate()) {
-                                Some(&ExternalLocation::Local) => {
-                                    if relative_to[0] == "std" {
-                                        let depth = relative_to.len() - 1;
-                                        "../".repeat(depth)
-                                    } else {
-                                        let depth = relative_to.len();
-                                        format!("{}std/", "../".repeat(depth))
-                                    }
-                                }
-                                Some(ExternalLocation::Remote(ref s)) => {
-                                    format!("{}/std/", s.trim_end_matches('/'))
-                                }
-                                Some(ExternalLocation::Unknown) | None => {
-                                    format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
-                                }
-                            };
-                            // This is a primitive so the url is done "by hand".
-                            let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
-                            Some(RenderedLink {
-                                original_text: s.clone(),
-                                new_text: link_text.clone(),
-                                href: format!(
-                                    "{}primitive.{}.html{}",
-                                    url,
-                                    &fragment[..tail],
-                                    &fragment[tail..]
-                                ),
-                            })
-                        } else {
-                            panic!("This isn't a primitive?!");
-                        }
+                debug!(?did);
+                if let Ok((mut href, ..)) = href(*did, cx) {
+                    debug!(?href);
+                    if let Some(ref fragment) = *fragment {
+                        href.push('#');
+                        href.push_str(fragment);
                     }
+                    Some(RenderedLink {
+                        original_text: s.clone(),
+                        new_text: link_text.clone(),
+                        href,
+                    })
+                } else {
+                    None
                 }
             })
             .collect()
@@ -531,18 +492,10 @@ pub fn from_def_id_and_attrs_and_parts(
             .get(&self.def_id)
             .map_or(&[][..], |v| v.as_slice())
             .iter()
-            .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
-                // FIXME(83083): using fragments as a side-channel for
-                // primitive names is very unfortunate
-                if did.is_some() || fragment.is_some() {
-                    Some(RenderedLink {
-                        original_text: s.clone(),
-                        new_text: link_text.clone(),
-                        href: String::new(),
-                    })
-                } else {
-                    None
-                }
+            .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
+                original_text: s.clone(),
+                new_text: link_text.clone(),
+                href: String::new(),
             })
             .collect()
     }
@@ -963,7 +916,7 @@ fn from_iter<T>(iter: T) -> Self
     crate other_attrs: Vec<ast::Attribute>,
 }
 
-#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
@@ -975,7 +928,7 @@ fn from_iter<T>(iter: T) -> Self
     /// This may not be the same as `link` if there was a disambiguator
     /// in an intra-doc link (e.g. \[`fn@f`\])
     pub(crate) link_text: String,
-    pub(crate) did: Option<DefId>,
+    pub(crate) did: DefId,
     /// The url fragment to append to the link
     pub(crate) fragment: Option<String>,
 }
@@ -1158,7 +1111,7 @@ impl GenericBound {
     crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+        let path = external_path(cx, did, false, vec![], empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
             PolyTrait {
@@ -1802,6 +1755,39 @@ impl PrimitiveType {
             Never => sym::never,
         }
     }
+
+    /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
+    /// Panics if there is no such module.
+    ///
+    /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
+    /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
+    /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
+    /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
+    crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
+        static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
+        PRIMITIVE_LOCATIONS.get_or_init(|| {
+            let mut primitive_locations = FxHashMap::default();
+            // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
+            // This is a degenerate case that I don't plan to support.
+            for &crate_num in tcx.crates(()) {
+                let e = ExternalCrate { crate_num };
+                let crate_name = e.name(tcx);
+                debug!(?crate_num, ?crate_name);
+                for &(def_id, prim) in &e.primitives(tcx) {
+                    // HACK: try to link to std instead where possible
+                    if crate_name == sym::core && primitive_locations.contains_key(&prim) {
+                        continue;
+                    }
+                    primitive_locations.insert(prim, def_id);
+                }
+            }
+            let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
+            for (def_id, prim) in local_primitives {
+                primitive_locations.insert(prim, def_id);
+            }
+            primitive_locations
+        })
+    }
 }
 
 impl From<ast::IntTy> for PrimitiveType {
@@ -2202,7 +2188,6 @@ impl Import {
 #[derive(Clone, Debug)]
 crate struct Macro {
     crate source: String,
-    crate imported_from: Option<Symbol>,
 }
 
 #[derive(Clone, Debug)]
index de2cd60d2edcd048cca1cc1d4151c7ecea0aba2d..b0021d1234cd610ecdabb6494631ef10624dcffd 100644 (file)
     let krate = cx.tcx.hir().krate();
     let module = crate::visit_ast::RustdocVisitor::new(cx).visit(krate);
 
-    cx.cache.deref_trait_did = cx.tcx.lang_items().deref_trait();
-    cx.cache.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
-    cx.cache.owned_box_did = cx.tcx.lang_items().owned_box();
-
     let mut externs = Vec::new();
     for &cnum in cx.tcx.crates(()).iter() {
         externs.push(ExternalCrate { crate_num: cnum });
@@ -97,7 +93,7 @@
 
 fn external_generic_args(
     cx: &mut DocContext<'_>,
-    trait_did: Option<DefId>,
+    did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
     substs: SubstsRef<'_>,
@@ -125,42 +121,38 @@ fn external_generic_args(
         })
         .collect();
 
-    match trait_did {
-        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
-        Some(did) if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() => {
-            assert!(ty_kind.is_some());
-            let inputs = match ty_kind {
-                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
-                _ => return GenericArgs::AngleBracketed { args, bindings },
-            };
-            let output = None;
-            // FIXME(#20299) return type comes from a projection now
-            // match types[1].kind {
-            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
-            //     _ => Some(types[1].clean(cx))
-            // };
-            GenericArgs::Parenthesized { inputs, output }
-        }
-        _ => GenericArgs::AngleBracketed { args, bindings },
+    if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
+        let inputs = match ty_kind.unwrap() {
+            ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
+            _ => return GenericArgs::AngleBracketed { args, bindings },
+        };
+        let output = None;
+        // FIXME(#20299) return type comes from a projection now
+        // match types[1].kind {
+        //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
+        //     _ => Some(types[1].clean(cx))
+        // };
+        GenericArgs::Parenthesized { inputs, output }
+    } else {
+        GenericArgs::AngleBracketed { args, bindings }
     }
 }
 
-// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
-// from Fn<(A, B,), C> to Fn(A, B) -> C
 pub(super) fn external_path(
     cx: &mut DocContext<'_>,
-    name: Symbol,
-    trait_did: Option<DefId>,
+    did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
     substs: SubstsRef<'_>,
 ) -> Path {
+    let def_kind = cx.tcx.def_kind(did);
+    let name = cx.tcx.item_name(did);
     Path {
         global: false,
-        res: Res::Err,
+        res: Res::Def(def_kind, did),
         segments: vec![PathSegment {
             name,
-            args: external_generic_args(cx, trait_did, has_self, bindings, substs),
+            args: external_generic_args(cx, did, has_self, bindings, substs),
         }],
     }
 }
@@ -409,8 +401,8 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
 }
 
 /// Given a type Path, resolve it to a Type using the TyCtxt
-crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Type {
-    debug!("resolve_type({:?},{:?})", path, id);
+crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
+    debug!("resolve_type({:?})", path);
 
     let is_generic = match path.res {
         Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)),
@@ -418,7 +410,7 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: &'tcx ty::Const<'tc
             return Generic(kw::SelfUpper);
         }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
-            return Generic(Symbol::intern(&path.whole_name()));
+            return Generic(path.segments[0].name);
         }
         Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
         _ => false,
index 97930f106994a3a95df9fe2b1be22d098c0c97f6..ac440a395155c8af38184c533367193eecf73a93 100644 (file)
@@ -137,7 +137,7 @@ fn try_from(value: &str) -> Result<Self, Self::Error> {
     crate manual_passes: Vec<String>,
     /// Whether to display warnings during doc generation or while gathering doctests. By default,
     /// all non-rustdoc-specific lints are allowed when generating docs.
-    crate display_warnings: bool,
+    crate display_doctest_warnings: bool,
     /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
     /// with and without documentation.
     crate show_coverage: bool,
@@ -192,7 +192,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
-            .field("display_warnings", &self.display_warnings)
+            .field("display_doctest_warnings", &self.display_doctest_warnings)
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
             .field("render_options", &self.render_options)
@@ -632,7 +632,7 @@ fn println_condition(condition: Condition) {
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
-        let display_warnings = matches.opt_present("display-warnings");
+        let display_doctest_warnings = matches.opt_present("display-doctest-warnings");
         let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
         let enable_minification = !matches.opt_present("disable-minification");
@@ -696,7 +696,7 @@ fn println_condition(condition: Condition) {
             test_args,
             default_passes,
             manual_passes,
-            display_warnings,
+            display_doctest_warnings,
             show_coverage,
             crate_version,
             test_run_directory,
index bd1d970fc199b6237515bb90518e28d643f2d748..765c77d5646cc7cd70ca0e8597eb3b1ca3a621a2 100644 (file)
@@ -204,7 +204,6 @@ impl<'tcx> DocContext<'tcx> {
         lint_opts,
         describe_lints,
         lint_cap,
-        display_warnings,
         ..
     }: RustdocOptions,
 ) -> rustc_interface::Config {
@@ -237,7 +236,7 @@ impl<'tcx> DocContext<'tcx> {
         maybe_sysroot,
         search_paths: libs,
         crate_types,
-        lint_opts: if !display_warnings { lint_opts } else { vec![] },
+        lint_opts,
         lint_cap,
         cg: codegen_options,
         externs,
@@ -330,18 +329,14 @@ impl<'tcx> DocContext<'tcx> {
 
     // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
     tcx.sess.time("item_types_checking", || {
-        for &module in tcx.hir().krate().modules.keys() {
-            tcx.ensure().check_mod_item_types(module);
-        }
+        tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
     });
     tcx.sess.abort_if_errors();
     tcx.sess.time("missing_docs", || {
         rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
     });
     tcx.sess.time("check_mod_attrs", || {
-        for &module in tcx.hir().krate().modules.keys() {
-            tcx.ensure().check_mod_attrs(module);
-        }
+        tcx.hir().for_each_module(|module| tcx.ensure().check_mod_attrs(module))
     });
     rustc_passes::stability::check_unused_or_stable_features(tcx);
 
index 9b740acfcdfd7fe598e0e152e2e430008af5a58d..a5fab1b3d42170c7f7ccdd527dae9dca37820cf6 100644 (file)
@@ -11,7 +11,7 @@
 
 use std::fs;
 use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::string::ToString;
 use std::sync::mpsc::Sender;
 
@@ -55,17 +55,17 @@ impl DocFS {
         fs::create_dir_all(path)
     }
 
-    crate fn write<P, C, E>(&self, path: P, contents: C) -> Result<(), E>
+    crate fn write<E>(
+        &self,
+        path: PathBuf,
+        contents: impl 'static + Send + AsRef<[u8]>,
+    ) -> Result<(), E>
     where
-        P: AsRef<Path>,
-        C: AsRef<[u8]>,
         E: PathError,
     {
         if !self.sync_only && cfg!(windows) {
             // A possible future enhancement after more detailed profiling would
             // be to create the file sync so errors are reported eagerly.
-            let path = path.as_ref().to_path_buf();
-            let contents = contents.as_ref().to_vec();
             let sender = self.errors.clone().expect("can't write after closing");
             rayon::spawn(move || {
                 fs::write(&path, contents).unwrap_or_else(|e| {
index e6097f5cad7f30688168a3107bec371e08891826..dbeea9cddf3879af8b2ac43683d6e89dac7e199b 100644 (file)
@@ -40,7 +40,7 @@
     crate no_crate_inject: bool,
     /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
     /// the default `#![allow(unused)]`.
-    crate display_warnings: bool,
+    crate display_doctest_warnings: bool,
     /// Additional crate-level attributes to add to doctests.
     crate attrs: Vec<String>,
 }
@@ -72,8 +72,8 @@
         maybe_sysroot: options.maybe_sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types,
-        lint_opts: if !options.display_warnings { lint_opts } else { vec![] },
-        lint_cap: Some(options.lint_cap.clone().unwrap_or_else(|| lint::Forbid)),
+        lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
+        lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)),
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
         unstable_features: options.render_options.unstable_features,
     };
 
     let test_args = options.test_args.clone();
-    let display_warnings = options.display_warnings;
+    let display_doctest_warnings = options.display_doctest_warnings;
     let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
                 let mut opts = scrape_test_config(crate_attrs);
-                opts.display_warnings |= options.display_warnings;
+                opts.display_doctest_warnings |= options.display_doctest_warnings;
                 let enable_per_target_ignores = options.enable_per_target_ignores;
                 let mut collector = Collector::new(
                     tcx.crate_name(LOCAL_CRATE),
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    run_tests(test_args, nocapture, display_warnings, tests);
+    run_tests(test_args, nocapture, display_doctest_warnings, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
 crate fn run_tests(
     mut test_args: Vec<String>,
     nocapture: bool,
-    display_warnings: bool,
+    display_doctest_warnings: bool,
     tests: Vec<test::TestDescAndFn>,
 ) {
     test_args.insert(0, "rustdoctest".to_string());
     if nocapture {
         test_args.push("--nocapture".to_string());
     }
-    test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+    test::test_main(
+        &test_args,
+        tests,
+        Some(test::Options::new().display_output(display_doctest_warnings)),
+    );
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
@@ -224,7 +228,7 @@ fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
 
     let mut opts =
-        TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
+        TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -504,7 +508,7 @@ fn drop(&mut self) {
     let mut prog = String::new();
     let mut supports_color = false;
 
-    if opts.attrs.is_empty() && !opts.display_warnings {
+    if opts.attrs.is_empty() && !opts.display_doctest_warnings {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
index c49e45c0e25a0410797cbceca32165998e8b87d1..1851708096564380e3fab75ca8a3c1617e33ae59 100644 (file)
@@ -52,7 +52,8 @@ fn main() {
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts = TestOptions { no_crate_inject: true, display_warnings: false, attrs: vec![] };
+    let opts =
+        TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -215,10 +216,10 @@ fn make_test_dont_insert_main() {
 }
 
 #[test]
-fn make_test_display_warnings() {
+fn make_test_display_doctest_warnings() {
     // If the user is asking to display doctest warnings, suppress the default `allow(unused)`.
     let mut opts = TestOptions::default();
-    opts.display_warnings = true;
+    opts.display_doctest_warnings = true;
     let input = "assert_eq!(2+2, 4);";
     let expected = "fn main() {
 assert_eq!(2+2, 4);
index 1830909d944606e1799a3acc5f2f48889a6a5ef9..bcfcc3d70395c1e3b996a50df2b1ed44af66c4da 100644 (file)
@@ -6,7 +6,7 @@
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
-use crate::clean::{self, GetDefId, ItemId};
+use crate::clean::{self, GetDefId, ItemId, PrimitiveType};
 use crate::config::RenderOptions;
 use crate::fold::DocFolder;
 use crate::formats::item_type::ItemType;
@@ -98,9 +98,6 @@
     stripped_mod: bool,
 
     crate search_index: Vec<IndexItem>,
-    crate deref_trait_did: Option<DefId>,
-    crate deref_mut_trait_did: Option<DefId>,
-    crate owned_box_did: Option<DefId>,
 
     // In rare case where a structure is defined in one module but implemented
     // in another, if the implementing module is parsed before defining module,
@@ -159,17 +156,16 @@ impl Cache {
             self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
         }
 
-        // Cache where all known primitives have their documentation located.
-        //
-        // Favor linking to as local extern as possible, so iterate all crates in
-        // reverse topological order.
-        for &e in krate.externs.iter().rev() {
-            for &(def_id, prim) in &e.primitives(tcx) {
-                self.primitive_locations.insert(prim, def_id);
-            }
-        }
-        for &(def_id, prim) in &krate.primitives {
-            self.primitive_locations.insert(prim, def_id);
+        // FIXME: avoid this clone (requires implementing Default manually)
+        self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone();
+        for (prim, &def_id) in &self.primitive_locations {
+            let crate_name = tcx.crate_name(def_id.krate);
+            // Recall that we only allow primitive modules to be at the root-level of the crate.
+            // If that restriction is ever lifted, this will have to include the relative paths instead.
+            self.external_paths.insert(
+                def_id,
+                (vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive),
+            );
         }
 
         krate = CacheBuilder { tcx, cache: self }.fold_crate(krate);
index ea0458034899c54b2db6ff4368c8b7ba506a1c56..2fde0017dc80c63be5cb8a1ffc6728620da667f9 100644 (file)
@@ -509,7 +509,11 @@ fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
         if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
     }
 
-    if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
+    if !did.is_local()
+        && !cache.access_levels.is_public(did)
+        && !cache.document_private
+        && !cache.primitive_locations.values().any(|&id| id == did)
+    {
         return Err(HrefError::Private);
     }
 
@@ -517,6 +521,7 @@ fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
     let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
         Some(&(ref fqp, shortty)) => (fqp, shortty, {
             let module_fqp = to_module_fqp(shortty, fqp);
+            debug!(?fqp, ?shortty, ?module_fqp);
             href_relative_parts(module_fqp, relative_to)
         }),
         None => {
@@ -548,6 +553,7 @@ fn to_module_fqp(shortty: ItemType, fqp: &[String]) -> &[String] {
             url_parts.insert(0, root);
         }
     }
+    debug!(?url_parts);
     let last = &fqp.last().unwrap()[..];
     let filename;
     match shortty {
@@ -742,7 +748,7 @@ fn fmt_type<'cx>(
     use_absolute: bool,
     cx: &'cx Context<'_>,
 ) -> fmt::Result {
-    debug!("fmt_type(t = {:?})", t);
+    trace!("fmt_type(t = {:?})", t);
 
     match *t {
         clean::Generic(name) => write!(f, "{}", name),
index f8fc9243e14b95891549e9dd1b835f2e42cded95..ece3ee640e2a69a6f8193a4f2672032b87b8097c 100644 (file)
@@ -5,6 +5,7 @@
 //!
 //! Use the `render_with_highlighting` to highlight some rust code.
 
+use crate::clean::PrimitiveType;
 use crate::html::escape::Escape;
 use crate::html::render::Context;
 
@@ -584,6 +585,13 @@ fn string<T: Display>(
                             .ok()
                             .map(|(url, _, _)| url)
                     }
+                    LinkFromSrc::Primitive(prim) => format::href_with_root_path(
+                        PrimitiveType::primitive_locations(context.tcx())[&prim],
+                        context,
+                        Some(context_info.root_path),
+                    )
+                    .ok()
+                    .map(|(url, _, _)| url),
                 }
             })
         {
index 5cd5254f3282d00f6dc4be2d0a37ede3613ed41d..c971e231463cdc56dd1f58c5871e06a7537f9168 100644 (file)
@@ -48,7 +48,7 @@
 mod tests;
 
 /// Options for rendering Markdown in the main body of documentation.
-pub(crate) fn opts() -> Options {
+pub(crate) fn main_body_opts() -> Options {
     Options::ENABLE_TABLES
         | Options::ENABLE_FOOTNOTES
         | Options::ENABLE_STRIKETHROUGH
@@ -56,9 +56,13 @@ pub(crate) fn opts() -> Options {
         | Options::ENABLE_SMART_PUNCTUATION
 }
 
-/// A subset of [`opts()`] used for rendering summaries.
+/// Options for rendering Markdown in summaries (e.g., in search results).
 pub(crate) fn summary_opts() -> Options {
-    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES
+    Options::ENABLE_TABLES
+        | Options::ENABLE_FOOTNOTES
+        | Options::ENABLE_STRIKETHROUGH
+        | Options::ENABLE_TASKLISTS
+        | Options::ENABLE_SMART_PUNCTUATION
 }
 
 /// When `to_string` is called, this struct will emit the HTML corresponding to
@@ -441,6 +445,42 @@ fn next(&mut self) -> Option<Self::Item> {
     }
 }
 
+/// Wrap HTML tables into `<div>` to prevent having the doc blocks width being too big.
+struct TableWrapper<'a, I: Iterator<Item = Event<'a>>> {
+    inner: I,
+    stored_events: VecDeque<Event<'a>>,
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> TableWrapper<'a, I> {
+    fn new(iter: I) -> Self {
+        Self { inner: iter, stored_events: VecDeque::new() }
+    }
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> Iterator for TableWrapper<'a, I> {
+    type Item = Event<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if let Some(first) = self.stored_events.pop_front() {
+            return Some(first);
+        }
+
+        let event = self.inner.next()?;
+
+        Some(match event {
+            Event::Start(Tag::Table(t)) => {
+                self.stored_events.push_back(Event::Start(Tag::Table(t)));
+                Event::Html(CowStr::Borrowed("<div>"))
+            }
+            Event::End(Tag::Table(t)) => {
+                self.stored_events.push_back(Event::Html(CowStr::Borrowed("</div>")));
+                Event::End(Tag::Table(t))
+            }
+            e => e,
+        })
+    }
+}
+
 type SpannedEvent<'a> = (Event<'a>, Range<usize>);
 
 /// Make headings links with anchor IDs and build up TOC.
@@ -981,7 +1021,7 @@ pub fn into_string(self) -> String {
             }
         };
 
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+        let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
         let p = p.into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
@@ -989,6 +1029,7 @@ pub fn into_string(self) -> String {
         let p = HeadingLinks::new(p, None, &mut ids);
         let p = Footnotes::new(p);
         let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+        let p = TableWrapper::new(p);
         let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
@@ -1000,7 +1041,7 @@ impl MarkdownWithToc<'_> {
     crate fn into_string(self) -> String {
         let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
 
-        let p = Parser::new_ext(md, opts()).into_offset_iter();
+        let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
@@ -1009,7 +1050,8 @@ impl MarkdownWithToc<'_> {
         {
             let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
             let p = Footnotes::new(p);
-            let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+            let p = TableWrapper::new(p.map(|(ev, _)| ev));
+            let p = CodeBlocks::new(p, codes, edition, playground);
             html::push_html(&mut s, p);
         }
 
@@ -1025,7 +1067,7 @@ impl MarkdownHtml<'_> {
         if md.is_empty() {
             return String::new();
         }
-        let p = Parser::new_ext(md, opts()).into_offset_iter();
+        let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
         // Treat inline HTML as plain text.
         let p = p.map(|event| match event.0 {
@@ -1037,7 +1079,8 @@ impl MarkdownHtml<'_> {
 
         let p = HeadingLinks::new(p, None, &mut ids);
         let p = Footnotes::new(p);
-        let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+        let p = TableWrapper::new(p.map(|(ev, _)| ev));
+        let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -1099,7 +1142,7 @@ fn markdown_summary_with_limit(
         }
     };
 
-    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+    let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
     let mut p = LinkReplacer::new(p, link_names);
 
     let mut buf = HtmlWithLimit::new(length_limit);
@@ -1246,7 +1289,8 @@ fn markdown_summary_with_limit(
         });
         None
     };
-    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter();
+    let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push))
+        .into_offset_iter();
 
     // There's no need to thread an IdMap through to here because
     // the IDs generated aren't going to be emitted anywhere.
@@ -1285,7 +1329,7 @@ fn markdown_summary_with_limit(
         return code_blocks;
     }
 
-    let mut p = Parser::new_ext(md, opts()).into_offset_iter();
+    let mut p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
     while let Some((event, offset)) = p.next() {
         if let Event::Start(Tag::CodeBlock(syntax)) = event {
index 733bedfdde9b487d2eee214069d469513a5fe366..b99d2fe5aa0d17584ca78cbba5e80ddf75f129d2 100644 (file)
@@ -69,7 +69,7 @@
 }
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(Context<'_>, 104);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
@@ -574,7 +574,7 @@ fn after_krate(&mut self) -> Result<(), Error> {
             |buf: &mut Buffer| all.print(buf),
             &self.shared.style_files,
         );
-        self.shared.fs.write(final_file, v.as_bytes())?;
+        self.shared.fs.write(final_file, v)?;
 
         // Generating settings page.
         page.title = "Rustdoc settings";
@@ -596,14 +596,14 @@ fn after_krate(&mut self) -> Result<(), Error> {
             )?,
             &style_files,
         );
-        self.shared.fs.write(&settings_file, v.as_bytes())?;
+        self.shared.fs.write(settings_file, v)?;
         if let Some(ref redirections) = self.shared.redirections {
             if !redirections.borrow().is_empty() {
                 let redirect_map_path =
                     self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
                 let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
                 self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
-                self.shared.fs.write(&redirect_map_path, paths.as_bytes())?;
+                self.shared.fs.write(redirect_map_path, paths)?;
             }
         }
 
@@ -641,7 +641,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
         if !buf.is_empty() {
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join("index.html");
-            scx.fs.write(&joint_dst, buf.as_bytes())?;
+            scx.fs.write(joint_dst, buf)?;
         }
 
         // Render sidebar-items.js used throughout this module.
@@ -653,7 +653,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
             let items = self.build_sidebar_items(module);
             let js_dst = self.dst.join("sidebar-items.js");
             let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
-            scx.fs.write(&js_dst, &v)?;
+            scx.fs.write(js_dst, v)?;
         }
         Ok(())
     }
@@ -687,7 +687,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
             let file_name = &item_path(item_type, &name.as_str());
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join(file_name);
-            self.shared.fs.write(&joint_dst, buf.as_bytes())?;
+            self.shared.fs.write(joint_dst, buf)?;
 
             if !self.render_redirect_pages {
                 self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
@@ -705,7 +705,7 @@ fn item(&mut self, item: clean::Item) -> Result<(), Error> {
                 } else {
                     let v = layout::redirect(file_name);
                     let redir_dst = self.dst.join(redir_name);
-                    self.shared.fs.write(&redir_dst, v.as_bytes())?;
+                    self.shared.fs.write(redir_dst, v)?;
                 }
             }
         }
index 172fe5d164b7afc1f123971b97a2d7fa5b8b4d76..1f27357f6c6eaf938c219dae0a3320594cd2849d 100644 (file)
@@ -51,6 +51,7 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
 use rustc_middle::middle::stability;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{kw, sym, Symbol};
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
@@ -224,7 +225,6 @@ struct AllTypes {
     opaque_tys: FxHashSet<ItemEntry>,
     statics: FxHashSet<ItemEntry>,
     constants: FxHashSet<ItemEntry>,
-    keywords: FxHashSet<ItemEntry>,
     attributes: FxHashSet<ItemEntry>,
     derives: FxHashSet<ItemEntry>,
     trait_aliases: FxHashSet<ItemEntry>,
@@ -245,7 +245,6 @@ fn new() -> AllTypes {
             opaque_tys: new_set(100),
             statics: new_set(100),
             constants: new_set(100),
-            keywords: new_set(100),
             attributes: new_set(100),
             derives: new_set(100),
             trait_aliases: new_set(100),
@@ -1069,13 +1068,13 @@ fn render_assoc_items(
         return;
     }
     if !traits.is_empty() {
-        let deref_impl = traits
-            .iter()
-            .find(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did);
+        let deref_impl = traits.iter().find(|t| {
+            t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait()
+        });
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits
-                .iter()
-                .any(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_mut_trait_did);
+            let has_deref_mut = traits.iter().any(|t| {
+                t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_mut_trait()
+            });
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -1165,7 +1164,7 @@ fn render_deref_methods(
     }
 }
 
-fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bool {
+fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
     let self_type_opt = match *item.kind {
         clean::MethodItem(ref method, _) => method.decl.self_type(),
         clean::TyMethodItem(ref method) => method.decl.self_type(),
@@ -1179,7 +1178,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo
                 (mutability == Mutability::Mut, false, false)
             }
             SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
-                (false, Some(did) == cache.owned_box_did, false)
+                (false, Some(did) == tcx.lang_items().owned_box(), false)
             }
             SelfTy::SelfValue => (false, false, true),
             _ => (false, false, false),
@@ -1302,7 +1301,7 @@ fn doc_impl_item(
             && match render_mode {
                 RenderMode::Normal => true,
                 RenderMode::ForDeref { mut_: deref_mut_ } => {
-                    should_render_item(&item, deref_mut_, cx.cache())
+                    should_render_item(&item, deref_mut_, cx.tcx())
                 }
             };
 
@@ -1800,13 +1799,13 @@ fn get_methods(
     for_deref: bool,
     used_links: &mut FxHashSet<String>,
     deref_mut: bool,
-    cache: &Cache,
+    tcx: TyCtxt<'_>,
 ) -> Vec<String> {
     i.items
         .iter()
         .filter_map(|item| match item.name {
             Some(ref name) if !name.is_empty() && item.is_method() => {
-                if !for_deref || should_render_item(item, deref_mut, cache) {
+                if !for_deref || should_render_item(item, deref_mut, tcx) {
                     Some(format!(
                         "<a href=\"#{}\">{}</a>",
                         get_next_url(used_links, format!("method.{}", name)),
@@ -1868,7 +1867,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             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, cache))
+                .flat_map(move |i| {
+                    get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())
+                })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 // We want links' order to be reproducible so we don't use unstable sort.
@@ -1886,11 +1887,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
         }
 
         if v.iter().any(|i| i.inner_impl().trait_.is_some()) {
-            if let Some(impl_) = v
-                .iter()
-                .filter(|i| i.inner_impl().trait_.is_some())
-                .find(|i| i.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did)
-            {
+            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.tcx().lang_items().deref_trait()
+            }) {
                 sidebar_deref_methods(cx, out, impl_, v);
             }
 
@@ -1988,10 +1987,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 }
             }
         }
-        let deref_mut = v
-            .iter()
-            .filter(|i| i.inner_impl().trait_.is_some())
-            .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did);
+        let deref_mut = v.iter().filter(|i| i.inner_impl().trait_.is_some()).any(|i| {
+            i.inner_impl().trait_.def_id_full(c) == cx.tcx().lang_items().deref_mut_trait()
+        });
         let inner_impl = target
             .def_id_full(c)
             .or_else(|| {
@@ -2004,7 +2002,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
             let mut ret = impls
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
-                .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c))
+                .flat_map(|i| {
+                    get_methods(i.inner_impl(), true, &mut used_links, deref_mut, cx.tcx())
+                })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 write!(
index 470749ef7b3387759cc295e21533a43bab114636..52505f2d634717fa70f06a43f59d0a528a24b0f7 100644 (file)
@@ -256,6 +256,10 @@ fn cmp(
 
     debug!("{:?}", indices);
     let mut curty = None;
+    // See: https://github.com/rust-lang/rust/issues/88545
+    let item_table_block_size = 900usize;
+    let mut item_table_nth_element = 0usize;
+
     for &idx in &indices {
         let myitem = &items[idx];
         if myitem.is_stripped() {
@@ -275,11 +279,13 @@ fn cmp(
             write!(
                 w,
                 "<h2 id=\"{id}\" class=\"section-header\">\
-                       <a href=\"#{id}\">{name}</a></h2>\n{}",
+                    <a href=\"#{id}\">{name}</a>\
+                 </h2>\n{}",
                 ITEM_TABLE_OPEN,
                 id = cx.derive_id(short.to_owned()),
                 name = name
             );
+            item_table_nth_element = 0;
         }
 
         match *myitem.kind {
@@ -386,6 +392,13 @@ fn cmp(
                 );
             }
         }
+
+        item_table_nth_element += 1;
+        if item_table_nth_element > item_table_block_size {
+            w.write_str(ITEM_TABLE_CLOSE);
+            w.write_str(ITEM_TABLE_OPEN);
+            item_table_nth_element = 0;
+        }
     }
 
     if curty.is_some() {
@@ -944,15 +957,15 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
 }
 
 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()
-    {
+    for (i, ty) in s.iter().enumerate() {
         if i > 0 {
             w.write_str(",&nbsp;");
         }
-        write!(w, "{}", ty.print(cx));
+        match *ty.kind {
+            clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
+            clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)),
+            _ => unreachable!(),
+        }
     }
 }
 
@@ -1068,24 +1081,27 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     name = variant.name.as_ref().unwrap(),
                 );
                 for field in fields {
-                    use crate::clean::StructFieldItem;
-                    if let StructFieldItem(ref ty) = *field.kind {
-                        let id = cx.derive_id(format!(
-                            "variant.{}.field.{}",
-                            variant.name.as_ref().unwrap(),
-                            field.name.as_ref().unwrap()
-                        ));
-                        write!(
-                            w,
-                            "<span id=\"{id}\" class=\"variant small-section-header\">\
-                                 <a href=\"#{id}\" class=\"anchor field\"></a>\
-                                 <code>{f}:&nbsp;{t}</code>\
-                             </span>",
-                            id = id,
-                            f = field.name.as_ref().unwrap(),
-                            t = ty.print(cx)
-                        );
-                        document(w, cx, field, Some(variant));
+                    match *field.kind {
+                        clean::StrippedItem(box clean::StructFieldItem(_)) => {}
+                        clean::StructFieldItem(ref ty) => {
+                            let id = cx.derive_id(format!(
+                                "variant.{}.field.{}",
+                                variant.name.as_ref().unwrap(),
+                                field.name.as_ref().unwrap()
+                            ));
+                            write!(
+                                w,
+                                "<span id=\"{id}\" class=\"variant small-section-header\">\
+                                    <a href=\"#{id}\" class=\"anchor field\"></a>\
+                                    <code>{f}:&nbsp;{t}</code>\
+                                </span>",
+                                id = id,
+                                f = field.name.as_ref().unwrap(),
+                                t = ty.print(cx)
+                            );
+                            document(w, cx, field, Some(variant));
+                        }
+                        _ => unreachable!(),
                     }
                 }
                 w.write_str("</div></div>");
index 54476d9c9a459f19b34179f57caa25512baf5159..d517f3ac0e3a9e1a16db7d886a31dc263bedc90b 100644 (file)
@@ -1,4 +1,4 @@
-use crate::clean;
+use crate::clean::{self, PrimitiveType};
 use crate::html::sources;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -22,6 +22,7 @@
 crate enum LinkFromSrc {
     Local(clean::Span),
     External(DefId),
+    Primitive(PrimitiveType),
 }
 
 /// This function will do at most two things:
@@ -73,17 +74,20 @@ fn handle_path(&mut self, path: &rustc_hir::Path<'_>, path_span: Option<Span>) {
                 Some(def_id)
             }
             Res::Local(_) => None,
+            Res::PrimTy(p) => {
+                // FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
+                let span = path_span.unwrap_or(path.span);
+                self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
+                return;
+            }
             Res::Err => return,
             _ => return,
         };
         if let Some(span) = self.tcx.hir().res_span(path.res) {
-            self.matches.insert(
-                path_span.unwrap_or_else(|| path.span),
-                LinkFromSrc::Local(clean::Span::new(span)),
-            );
-        } else if let Some(def_id) = info {
             self.matches
-                .insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id));
+                .insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span)));
+        } else if let Some(def_id) = info {
+            self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id));
         }
     }
 }
index 99cd98f7eaeb84592f18d3287bc35f85cef10842..c1a83ad5820cb9067b329fc6590f783755198349 100644 (file)
@@ -105,10 +105,10 @@ fn suffix_path(&self, filename: &str) -> PathBuf {
         self.dst.join(&filename)
     }
 
-    fn write_shared<C: AsRef<[u8]>>(
+    fn write_shared(
         &self,
         resource: SharedResource<'_>,
-        contents: C,
+        contents: impl 'static + Send + AsRef<[u8]>,
         emit: &[EmitType],
     ) -> Result<(), Error> {
         if resource.should_emit(emit) {
@@ -121,25 +121,23 @@ fn write_shared<C: AsRef<[u8]>>(
     fn write_minify(
         &self,
         resource: SharedResource<'_>,
-        contents: &str,
+        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
         minify: bool,
         emit: &[EmitType],
     ) -> Result<(), Error> {
-        let tmp;
-        let contents = if minify {
-            tmp = if resource.extension() == Some(&OsStr::new("css")) {
+        if minify {
+            let contents = contents.as_ref();
+            let contents = if resource.extension() == Some(&OsStr::new("css")) {
                 minifier::css::minify(contents).map_err(|e| {
                     Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
                 })?
             } else {
                 minifier::js::minify(contents)
             };
-            tmp.as_bytes()
+            self.write_shared(resource, contents, emit)
         } else {
-            contents.as_bytes()
-        };
-
-        self.write_shared(resource, contents, emit)
+            self.write_shared(resource, contents, emit)
+        }
     }
 }
 
@@ -155,15 +153,21 @@ pub(super) fn write_shared(
     let lock_file = cx.dst.join(".lock");
     let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
 
-    // The weird `: &_` is to work around a borrowck bug: https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723
-    let write_minify = |p, c: &_| {
+    // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly.
+    fn write_minify(
+        basename: &'static str,
+        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
+        cx: &Context<'_>,
+        options: &RenderOptions,
+    ) -> Result<(), Error> {
         cx.write_minify(
-            SharedResource::ToolchainSpecific { basename: p },
-            c,
+            SharedResource::ToolchainSpecific { basename },
+            contents,
             options.enable_minification,
             &options.emit,
         )
-    };
+    }
+
     // Toolchain resources should never be dynamic.
     let write_toolchain = |p: &'static _, c: &'static _| {
         cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit)
@@ -210,12 +214,12 @@ fn add_background_image_to_css(
         "details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
         "toggle-plus.svg",
     );
-    write_minify("rustdoc.css", &rustdoc_css)?;
+    write_minify("rustdoc.css", rustdoc_css, cx, options)?;
 
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
-    write_minify("settings.css", static_files::SETTINGS_CSS)?;
-    write_minify("noscript.css", static_files::NOSCRIPT_CSS)?;
+    write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?;
+    write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
@@ -228,9 +232,9 @@ fn add_background_image_to_css(
 
         // Handle the official themes
         match theme {
-            "light" => write_minify("light.css", static_files::themes::LIGHT)?,
-            "dark" => write_minify("dark.css", static_files::themes::DARK)?,
-            "ayu" => write_minify("ayu.css", static_files::themes::AYU)?,
+            "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
+            "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
+            "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
             _ => {
                 // Handle added third-party themes
                 let filename = format!("{}.{}", theme, extension);
@@ -264,26 +268,38 @@ fn add_background_image_to_css(
     // Maybe we can change the representation to move this out of main.js?
     write_minify(
         "main.js",
-        &static_files::MAIN_JS.replace(
-            "/* INSERT THEMES HERE */",
-            &format!(" = {}", serde_json::to_string(&themes).unwrap()),
-        ),
+        static_files::MAIN_JS
+            .replace(
+                "/* INSERT THEMES HERE */",
+                &format!(" = {}", serde_json::to_string(&themes).unwrap()),
+            )
+            .replace(
+                "/* INSERT RUSTDOC_VERSION HERE */",
+                &format!(
+                    "rustdoc {}",
+                    rustc_interface::util::version_str().unwrap_or("unknown version")
+                ),
+            ),
+        cx,
+        options,
     )?;
-    write_minify("search.js", static_files::SEARCH_JS)?;
-    write_minify("settings.js", static_files::SETTINGS_JS)?;
+    write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
+    write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
 
     if cx.include_sources {
-        write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?;
+        write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
     }
 
     {
         write_minify(
             "storage.js",
-            &format!(
+            format!(
                 "var resourcesSuffix = \"{}\";{}",
                 cx.shared.resource_suffix,
                 static_files::STORAGE_JS
             ),
+            cx,
+            options,
         )?;
     }
 
@@ -292,12 +308,12 @@ fn add_background_image_to_css(
         // This varies based on the invocation, so it can't go through the write_minify wrapper.
         cx.write_minify(
             SharedResource::InvocationSpecific { basename: "theme.css" },
-            &buffer,
+            buffer,
             options.enable_minification,
             &options.emit,
         )?;
     }
-    write_minify("normalize.css", static_files::NORMALIZE_CSS)?;
+    write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?;
     for (name, contents) in &*FILES_UNVERSIONED {
         cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?;
     }
@@ -512,7 +528,7 @@ fn to_json_string(&self) -> String {
                 content,
                 &cx.shared.style_files,
             );
-            cx.shared.fs.write(&dst, v.as_bytes())?;
+            cx.shared.fs.write(dst, v)?;
         }
     }
 
@@ -603,7 +619,7 @@ struct Implementor {
              }",
         );
         v.push_str("})()");
-        cx.shared.fs.write(&mydst, &v)?;
+        cx.shared.fs.write(mydst, v)?;
     }
     Ok(())
 }
index bb90b195ddd4f5547dfc9c19d79a12cac53736ec..71c64231a210eb48e92e2b7739b7bc08362df134 100644 (file)
@@ -208,7 +208,7 @@ fn emit_source(
             },
             &self.cx.shared.style_files,
         );
-        self.cx.shared.fs.write(&cur, v.as_bytes())?;
+        self.cx.shared.fs.write(cur, v)?;
         self.emitted_local_sources.insert(p);
         Ok(())
     }
index 23ca6eeaf3bb969be1af9f6ab6526bdfa12a0171..eb7cc9309f41641c6212ca6e244e8ad6fd5b43ef 100644 (file)
@@ -522,6 +522,11 @@ nav.sub {
        position: relative;
 }
 
+.docblock > * {
+       max-width: 100%;
+       overflow-x: auto;
+}
+
 .content .out-of-band {
        flex-grow: 0;
        text-align: right;
@@ -923,15 +928,24 @@ body.blur > :not(#help) {
        display: block;
        margin-right: 0.5rem;
 }
-#help > div > span {
+#help span.top, #help span.bottom {
        text-align: center;
        display: block;
-       margin: 10px 0;
        font-size: 18px;
-       border-bottom: 1px solid #ccc;
+
+}
+#help span.top {
+       text-align: center;
+       display: block;
+       margin: 10px 0;
+       border-bottom: 1px solid;
        padding-bottom: 4px;
        margin-bottom: 6px;
 }
+#help span.bottom {
+       clear: both;
+       border-top: 1px solid;
+}
 #help dd { margin: 5px 35px; }
 #help .infos { padding-left: 0; }
 #help h1, #help h2 { margin-top: 0; }
index f9ddef4120bbec8c69c0ba92ab2f3c854850f976..c79801e830876f77c0720756da2c3fa398052e13 100644 (file)
@@ -217,7 +217,7 @@ a {
        color: #c5c5c5;
 }
 body.source .example-wrap pre.rust a {
-       background: #c5c5c5;
+       background: #333;
 }
 
 .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
@@ -286,8 +286,8 @@ details.undocumented > summary::before {
        border-radius: 4px;
 }
 
-#help > div > span {
-       border-bottom-color: #5c6773;
+#help span.bottom, #help span.top {
+       border-color: #5c6773;
 }
 
 .since {
index d9348be6994e2a1d676cf3b8a6ea9c6e8ea57af0..d2e54070acd68621efadf5e506c9ffb9806aed1c 100644 (file)
@@ -242,8 +242,8 @@ details.undocumented > summary::before {
        border-color: #bfbfbf;
 }
 
-#help > div > span {
-       border-bottom-color: #bfbfbf;
+#help span.bottom, #help span.top {
+       border-color: #bfbfbf;
 }
 
 #help dt {
index 0ffe5929ea59376e14b0da7948a7de273cac808d..25d810560c1469b98397fd2975ad686c82c1165a 100644 (file)
@@ -232,8 +232,8 @@ details.undocumented > summary::before {
        border-color: #bfbfbf;
 }
 
-#help > div > span {
-       border-bottom-color: #bfbfbf;
+#help span.bottom, #help span.top {
+       border-color: #bfbfbf;
 }
 
 .since {
index 1eebd39256459e1e834f31022f6a32f2afb27cc0..e396fd9d288db1cc34da37279113f4a65683b0c7 100644 (file)
@@ -911,6 +911,7 @@ function hideThemeButtonState() {
         });
 
         var book_info = document.createElement("span");
+        book_info.className = "top";
         book_info.innerHTML = "You can find more information in \
             <a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
 
@@ -961,6 +962,14 @@ function hideThemeButtonState() {
         container.appendChild(div_shortcuts);
         container.appendChild(div_infos);
 
+        var rustdoc_version = document.createElement("span");
+        rustdoc_version.className = "bottom";
+        var rustdoc_version_code = document.createElement("code");
+        rustdoc_version_code.innerText = "/* INSERT RUSTDOC_VERSION HERE */";
+        rustdoc_version.appendChild(rustdoc_version_code);
+
+        container.appendChild(rustdoc_version);
+
         popup.appendChild(container);
         insertAfter(popup, searchState.outputElement());
         // So that it's only built once and then it'll do nothing when called!
index e6bbd237cda7d72f2f1320ae442c05cc6936f320..f8ea7a499b2340a4dcbd14e991d3f6131a1ba409 100644 (file)
@@ -30,9 +30,7 @@ pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
             .get(&item.def_id)
             .into_iter()
             .flatten()
-            .filter_map(|clean::ItemLink { link, did, .. }| {
-                did.map(|did| (link.clone(), from_item_id(did.into())))
-            })
+            .map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
             .collect();
         let docs = item.attrs.collapsed_doc_value();
         let attrs = item
index 8246834a74688040d3dc089d7cbefc3460b99d30..f170561300cc2d6ef780b4ce0dde10286ab2aa00 100644 (file)
@@ -419,8 +419,12 @@ fn opts() -> Vec<RustcOptGroup> {
                 "URL",
             )
         }),
-        unstable("display-warnings", |o| {
-            o.optflagmulti("", "display-warnings", "to print code warnings when testing doc")
+        unstable("display-doctest-warnings", |o| {
+            o.optflagmulti(
+                "",
+                "display-doctest-warnings",
+                "show warnings that originate in doctests",
+            )
         }),
         stable("crate-version", |o| {
             o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
index 80af2a7aaf5c8ab820ef593534f023a9dc22d073..2ae4897dc349625ede4dad13463a0c876eb26e08 100644 (file)
@@ -120,7 +120,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
-    opts.display_warnings = options.display_warnings;
+    opts.display_doctest_warnings = options.display_doctest_warnings;
     let mut collector = Collector::new(
         Symbol::intern(&options.input.display().to_string()),
         options.clone(),
@@ -138,7 +138,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
     crate::doctest::run_tests(
         options.test_args,
         options.nocapture,
-        options.display_warnings,
+        options.display_doctest_warnings,
         collector.tests,
     );
     Ok(())
index 56ef15eb8842017b1320425fb719f4cf8390895c..37faa6742927a2860a543ab97f36f5a42dd92ce7 100644 (file)
@@ -2,7 +2,7 @@
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use regex::Regex;
@@ -83,7 +83,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
                 });
             };
 
-            let mut p = Parser::new_ext(&dox, opts()).into_offset_iter();
+            let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
 
             while let Some((event, range)) = p.next() {
                 match event {
index 92e678e4c024ba9f3f67b8f2f3bba8aa35715570..721af3313d27f6d33d76888b36d25f9fbcc62818 100644 (file)
@@ -4,8 +4,10 @@
 use crate::html::markdown::{find_testable_code, ErrorCodes};
 use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
 use crate::passes::Pass;
+use rustc_hir as hir;
 use rustc_lint::builtin::MISSING_DOCS;
 use rustc_middle::lint::LintLevelSource;
+use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 use rustc_span::FileName;
 use serde::Serialize;
@@ -221,10 +223,42 @@ fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
                     .hir()
                     .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
                 let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
+
+                // In case we have:
+                //
+                // ```
+                // enum Foo { Bar(u32) }
+                // // or:
+                // struct Bar(u32);
+                // ```
+                //
+                // there is no need to require documentation on the fields of tuple variants and
+                // tuple structs.
+                let should_be_ignored = i
+                    .def_id
+                    .as_def_id()
+                    .and_then(|def_id| self.ctx.tcx.parent(def_id))
+                    .and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
+                    .map(|node| {
+                        matches!(
+                            node,
+                            hir::Node::Variant(hir::Variant {
+                                data: hir::VariantData::Tuple(_, _),
+                                ..
+                            }) | hir::Node::Item(hir::Item {
+                                kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _), _),
+                                ..
+                            })
+                        )
+                    })
+                    .unwrap_or(false);
+
                 // `missing_docs` is allow-by-default, so don't treat this as ignoring the item
-                // unless the user had an explicit `allow`
-                let should_have_docs =
-                    level != lint::Level::Allow || matches!(source, LintLevelSource::Default);
+                // unless the user had an explicit `allow`.
+                //
+                let should_have_docs = !should_be_ignored
+                    && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default));
+
                 debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
                 self.items.entry(filename).or_default().count_item(
                     has_docs,
index d961340f1f8d3993d0615d8b14d1fc095b430001..c9f66d096f06cdb383a50fe3380c5865700def95 100644 (file)
@@ -101,9 +101,9 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
                     );
                 } else if empty_block {
                     diag.span_suggestion(
-                        sp.from_inner(InnerSpan::new(0, 3)),
+                        sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
                         explanation,
-                        String::from("```text"),
+                        String::from("text"),
                         Applicability::MachineApplicable,
                     );
                 }
index 178c8c15a158861ca6483398e43650bf6c08f113..c0c37ee061198573e3cacc768966215563edaba5 100644 (file)
@@ -14,7 +14,7 @@
 };
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::{bug, ty};
+use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::ParentScope;
 use rustc_session::lint::Lint;
 use rustc_span::hygiene::{MacroKind, SyntaxContext};
@@ -98,14 +98,10 @@ fn name(self, tcx: TyCtxt<'_>) -> Symbol {
         }
     }
 
-    fn def_id(self) -> DefId {
-        self.opt_def_id().expect("called def_id() on a primitive")
-    }
-
-    fn opt_def_id(self) -> Option<DefId> {
+    fn def_id(self, tcx: TyCtxt<'_>) -> DefId {
         match self {
-            Res::Def(_, id) => Some(id),
-            Res::Primitive(_) => None,
+            Res::Def(_, id) => id,
+            Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(),
         }
     }
 
@@ -237,10 +233,7 @@ enum AnchorFailure {
     /// link, Rustdoc disallows having a user-specified anchor.
     ///
     /// Most of the time this is fine, because you can just link to the page of
-    /// the item if you want to provide your own anchor. For primitives, though,
-    /// rustdoc uses the anchor as a side channel to know which page to link to;
-    /// it doesn't show up in the generated link. Ideally, rustdoc would remove
-    /// this limitation, allowing you to link to subheaders on primitives.
+    /// the item if you want to provide your own anchor.
     RustdocAnchorConflict(Res),
 }
 
@@ -388,7 +381,7 @@ fn resolve_primitive_associated_item(
                         ty::AssocKind::Const => "associatedconstant",
                         ty::AssocKind::Type => "associatedtype",
                     };
-                    let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
+                    let fragment = format!("{}.{}", out, item_name);
                     (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
                 })
         })
@@ -475,14 +468,6 @@ fn resolve<'path>(
                     return handle_variant(self.cx, res, extra_fragment);
                 }
                 // Not a trait item; just return what we found.
-                Res::Primitive(ty) => {
-                    if extra_fragment.is_some() {
-                        return Err(ErrorKind::AnchorFailure(
-                            AnchorFailure::RustdocAnchorConflict(res),
-                        ));
-                    }
-                    return Ok((res, Some(ty.as_sym().to_string())));
-                }
                 _ => return Ok((res, extra_fragment.clone())),
             }
         }
@@ -517,6 +502,8 @@ fn resolve<'path>(
                 let (res, fragment, side_channel) =
                     self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
                 let result = if extra_fragment.is_some() {
+                    // NOTE: can never be a primitive since `side_channel.is_none()` only when `res`
+                    // is a trait (and the side channel DefId is always an associated item).
                     let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r));
                     Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res)))
                 } else {
@@ -1152,7 +1139,7 @@ fn resolve_link(
             module_id = DefId { krate, index: CRATE_DEF_INDEX };
         }
 
-        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(
+        let (mut res, fragment) = self.resolve_with_disambiguator_cached(
             ResolutionInfo {
                 module_id,
                 dis: disambiguator,
@@ -1174,16 +1161,7 @@ fn resolve_link(
             if let Some(prim) = resolve_primitive(path_str, TypeNS) {
                 // `prim@char`
                 if matches!(disambiguator, Some(Disambiguator::Primitive)) {
-                    if fragment.is_some() {
-                        anchor_failure(
-                            self.cx,
-                            diag_info,
-                            AnchorFailure::RustdocAnchorConflict(prim),
-                        );
-                        return None;
-                    }
                     res = prim;
-                    fragment = Some(prim.name(self.cx.tcx).to_string());
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
@@ -1303,12 +1281,17 @@ fn resolve_link(
                     }
                 }
 
-                Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
+                Some(ItemLink {
+                    link: ori_link.link,
+                    link_text,
+                    did: res.def_id(self.cx.tcx),
+                    fragment,
+                })
             }
             Res::Def(kind, id) => {
                 verify(kind, id)?;
                 let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
+                Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
             }
         }
     }
@@ -1323,7 +1306,7 @@ fn resolve_with_disambiguator_cached(
         if let Some(ref cached) = self.visited_links.get(&key) {
             match cached {
                 Some(cached) => {
-                    self.kind_side_channel.set(cached.side_channel.clone());
+                    self.kind_side_channel.set(cached.side_channel);
                     return Some(cached.res.clone());
                 }
                 None if cache_resolution_failure => return None,
@@ -2069,8 +2052,11 @@ fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: A
             diag.span_label(sp, "invalid anchor");
         }
         if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure {
-            diag.note("this restriction may be lifted in a future release");
-            diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information");
+            if let Some(sp) = sp {
+                span_bug!(sp, "anchors should be allowed now");
+            } else {
+                bug!("anchors should be allowed now");
+            }
         }
     });
 }
@@ -2198,10 +2184,11 @@ fn handle_variant(
     use rustc_middle::ty::DefIdTree;
 
     if extra_fragment.is_some() {
+        // NOTE: `res` can never be a primitive since this function is only called when `tcx.def_kind(res) == DefKind::Variant`.
         return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res)));
     }
     cx.tcx
-        .parent(res.def_id())
+        .parent(res.def_id(cx.tcx))
         .map(|parent| {
             let parent_def = Res::Def(DefKind::Enum, parent);
             let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
index 03bc2b52f178f5336d9047485688691d91d4bb70..279d0dbda82ee7b45378181870f882768106c245 100644 (file)
@@ -10,6 +10,7 @@
 use crate::fold::DocFolder;
 use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
 use crate::visit_ast::inherits_doc_hidden;
+use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
 use rustc_session::lint;
 use rustc_span::symbol::sym;
@@ -67,15 +68,35 @@ fn add_test(&mut self, _: String, config: LangString, _: usize) {
                 | clean::ImportItem(_)
                 | clean::PrimitiveItem(_)
                 | clean::KeywordItem(_)
+                // check for trait impl
+                | clean::ImplItem(clean::Impl { trait_: Some(_), .. })
         )
     {
         return false;
     }
+
     // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
     // would presumably panic if a fake `DefIndex` were passed.
     let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
+
+    // check if parent is trait impl
+    if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
+        if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) {
+            if matches!(
+                parent_node,
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }),
+                    ..
+                })
+            ) {
+                return false;
+            }
+        }
+    }
+
     if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
         || inherits_doc_hidden(cx.tcx, hir_id)
+        || cx.tcx.hir().span(hir_id).in_derive_expansion()
     {
         return false;
     }
index f29d38e3e078a51251edb7668d72fa0465f0a8ef..a0144a5298eba24b3d2cc94f0e6d562473c00d08 100644 (file)
@@ -2,7 +2,7 @@
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use std::iter::Peekable;
@@ -192,7 +192,7 @@ fn fold_item(&mut self, item: Item) -> Option<Item> {
             let mut is_in_comment = None;
             let mut in_code_block = false;
 
-            let p = Parser::new_ext(&dox, opts()).into_offset_iter();
+            let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
 
             for (event, range) in p {
                 match event {
index 3e06b4173144ca4a26d5a7831d5e8f680c21c3aa..3e98ba08fb9ca376dbb5b4e4b0d307811f909e6d 100644 (file)
@@ -67,7 +67,7 @@ fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLev
         }
     }
 
-    fn visit_item(&mut self, res: Res) {
+    fn visit_item(&mut self, res: Res<!>) {
         let def_id = res.def_id();
         let vis = self.tcx.visibility(def_id);
         let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None };
index ec995b75d71c5f3b9a82fe084259477eb22f74da..86c7daa627aefda1371568b948eba21edf720747 160000 (submodule)
@@ -1 +1 @@
-Subproject commit ec995b75d71c5f3b9a82fe084259477eb22f74da
+Subproject commit 86c7daa627aefda1371568b948eba21edf720747
index a692f6f896da724e69c4e4ec24163bc0e4ab1ec8..d60699efd36cb29aeb55e650a2b1211ba72938d8 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc-json-types"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [lib]
 path = "lib.rs"
diff --git a/src/test/assembly/niche-prefer-zero.rs b/src/test/assembly/niche-prefer-zero.rs
new file mode 100644 (file)
index 0000000..0ab37a6
--- /dev/null
@@ -0,0 +1,25 @@
+// Check that niche selection prefers zero and that jumps are optimized away.
+// See https://github.com/rust-lang/rust/pull/87794
+// assembly-output: emit-asm
+// only-x86
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Size {
+    One = 1,
+    Two = 2,
+    Three = 3,
+}
+
+#[no_mangle]
+pub fn handle(x: Option<Size>) -> u8 {
+    match x {
+        None => 0,
+        Some(size) => size as u8,
+    }
+}
+
+// There should be no jumps in output
+// CHECK-NOT: j
diff --git a/src/test/assembly/x86_64-sse_crc.rs b/src/test/assembly/x86_64-sse_crc.rs
new file mode 100644 (file)
index 0000000..cdbf057
--- /dev/null
@@ -0,0 +1,12 @@
+// only-x86_64
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
+
+// CHECK-LABEL: banana
+// CHECK: crc32
+#[no_mangle]
+pub unsafe fn banana(v: u8) -> u32 {
+    use std::arch::x86_64::*;
+    let out = !0u32;
+    _mm_crc32_u8(out, v)
+}
diff --git a/src/test/codegen/panic-in-drop-abort.rs b/src/test/codegen/panic-in-drop-abort.rs
new file mode 100644 (file)
index 0000000..62d0935
--- /dev/null
@@ -0,0 +1,54 @@
+// compile-flags: -Z panic-in-drop=abort -O
+
+// Ensure that unwinding code paths are eliminated from the output after
+// optimization.
+
+#![crate_type = "lib"]
+use std::any::Any;
+use std::mem::forget;
+
+pub struct ExternDrop;
+impl Drop for ExternDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call may potentially unwind.
+        extern "Rust" {
+            fn extern_drop();
+        }
+        unsafe {
+            extern_drop();
+        }
+    }
+}
+
+struct AssertNeverDrop;
+impl Drop for AssertNeverDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call should be optimized away as unreachable.
+        extern "C" {
+            fn should_not_appear_in_output();
+        }
+        unsafe {
+            should_not_appear_in_output();
+        }
+    }
+}
+
+// CHECK-LABEL: normal_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn normal_drop(x: ExternDrop) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
+
+// CHECK-LABEL: indirect_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn indirect_drop(x: Box<dyn Any>) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
diff --git a/src/test/codegen/sse42-implies-crc32.rs b/src/test/codegen/sse42-implies-crc32.rs
new file mode 100644 (file)
index 0000000..47b1a89
--- /dev/null
@@ -0,0 +1,16 @@
+// only-x86_64
+// min-llvm-version: 14.0
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse4.2")]
+#[no_mangle]
+pub unsafe fn crc32sse(v: u8) -> u32 {
+    use std::arch::x86_64::*;
+    let out = !0u32;
+    _mm_crc32_u8(out, v)
+}
+
+// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
index c35c32554983a6976d08789fb606d422d7713dd8..c8879856b9670c841d481c97db268e42943d744b 100644 (file)
 // cdb-command:dx f64
 // cdb-check:f64              : 3.500000 [Type: double]
 // cdb-command:.enable_unicode 1
+// FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str.
 // cdb-command:dx  s
-// cdb-check:s                : "Hello, World!" [Type: str]
+// cdb-check:s                : [...] [Type: str]
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
index 9463f82c797496b5a05f9fde1f3622f3dd47c1c4..642694355addf47e8e98d91cd192093ef926fc52 100644 (file)
@@ -1,63 +1,45 @@
 // only-cdb
-// ignore-tidy-linelength
 // compile-flags:-g
 
 // cdb-command: g
 
-// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
-//       so the best we can do is to make sure we are generating the right debuginfo.
-//       Therefore, we use the `!` [format specifier](https://docs.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2019#BKMK_Visual_Studio_2012_format_specifiers)
-//       to disable the natvis for a given expression. We also provide the `-r2` flag
-//       to expand the expression 2 levels.
-
-// cdb-command: dx -r2 a,!
-// cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
-// cdb-check:        [+0x000] __0              : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
-
-// cdb-command: dx -r2 b,!
-// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Some]
-// cdb-check:        [+0x000] __0              : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>::Discriminant$]
-
-// cdb-command: dx -r2 c,!
-// cdb-check:c,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check:        [+0x000] my_data          : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 d,!
-// cdb-check:d,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check:        [+0x000] my_data          : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 e,!
-// cdb-check:e,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
-// cdb-check:        [+0x000] my_data          : 0x13 [Type: msvc_pretty_enums::CStyleEnum]
-// cdb-check:    [+0x000] discriminant     : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
-
-// cdb-command: dx -r2 f,!
-// cdb-check:f,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
-// cdb-check:        [+0x000] __0              : 0x[...] : 0x1 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 g,!
-// cdb-check:g,!              [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Some]
-// cdb-check:        [+0x000] __0              : 0x0 [Type: unsigned int *]
-// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 h,!
-// cdb-check:h,!              : Some [Type: enum$<core::option::Option<u32> >]
-// cdb-check:    [+0x000] variant0         [Type: enum$<core::option::Option<u32> >::None]
-// cdb-check:    [+0x000] variant1         [Type: enum$<core::option::Option<u32> >::Some]
-// cdb-check:        [+0x004] __0              : 0xc [Type: unsigned int]
-// cdb-check:    [+0x000] discriminant     : Some (0x1) [Type: core::option::Option]
+// cdb-command: dx a
+// cdb-check:a                :  Some({...}) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [variant]        :  Some
+// cdb-check:    [+0x000] __0              : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
+
+// cdb-command: dx b
+// cdb-check:b                : None [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum> >, 2, 16, Some>]
+// cdb-check:    [variant]        : None
+
+// cdb-command: dx c
+// cdb-check:c                : Tag1 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [<Raw View>]     [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [variant]        : Tag1
+
+// cdb-command: dx d
+// cdb-check:d                :  Data({...}) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [<Raw View>]     [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [variant]        :  Data
+// cdb-check:    [+0x000] my_data          : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
+
+// cdb-command: dx e
+// cdb-check:e                : Tag2 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [<Raw View>]     [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [variant]        : Tag2
+
+// cdb-command: dx f
+// cdb-check:f                :  Some({...}) [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [variant]        :  Some
+// cdb-check:    [+0x000] __0              : 0x[...] : 0x1 [Type: unsigned int *]
+
+// cdb-command: dx g
+// cdb-check:g                : None [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<ref$<u32> >, 1, [...], Some>]
+// cdb-check:    [variant]        : None
 
 // cdb-command: dx h
 // cdb-check:h                : Some [Type: enum$<core::option::Option<u32> >]
 // cdb-check:    [variant]        : Some
 // cdb-check:    [+0x004] __0              : 0xc [Type: unsigned int]
 
-// cdb-command: dx -r2 i,!
-// cdb-check:i,!              : None [Type: enum$<core::option::Option<u32> >]
-// cdb-check:    [+0x000] variant0         [Type: enum$<core::option::Option<u32> >::None]
-// cdb-check:    [+0x000] variant1         [Type: enum$<core::option::Option<u32> >::Some]
-// cdb-check:        [+0x004] __0              : 0x[...] [Type: unsigned int]
-// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: core::option::Option]
-
 // cdb-command: dx i
 // cdb-check:i                : None [Type: enum$<core::option::Option<u32> >]
 // cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<u32> >]
 // cdb-command: dx j
 // cdb-check:j                : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
 
-// cdb-command: dx -r2 k,!
-// cdb-check:k,!              [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
-// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some]
-// cdb-check:        [+0x000] __0              [Type: alloc::string::String]
-// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
-
-// cdb-command: dx -r2 l,!
-// cdb-check:l,!              : $T2 [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
-// cdb-check:    [+0x000] Ok               [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>::Ok]
-// cdb-check:        [+0x000] __0              : 0x2a [Type: unsigned int]
+// cdb-command: dx k
+// cdb-check:k                :  Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:    [variant]        :  Some
+// cdb-check:    [+0x000] __0              : "IAMA optional string!" [Type: alloc::string::String]
+
+// cdb-command: dx l
+// cdb-check:l                :  Ok [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::result::Result<u32,enum$<msvc_pretty_enums::Empty> >, Ok>]
+// cdb-check:    [variant]        :  Ok
+// cdb-check:    [+0x000] __0              : 0x2a [Type: unsigned int]
 
 pub enum CStyleEnum {
     Low = 2,
diff --git a/src/test/debuginfo/msvc-scalarpair-params.rs b/src/test/debuginfo/msvc-scalarpair-params.rs
new file mode 100644 (file)
index 0000000..3846fb4
--- /dev/null
@@ -0,0 +1,101 @@
+// only-cdb
+// compile-flags: -g
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1               : (0xa..0xc) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2               : (0x14..0x1e) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1               : (0x9..0x64) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2               : (0xc..0x5a) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx o1
+// cdb-check:o1               : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check:    [variant]        : Some
+// cdb-check:    [+0x004] __0              : 0x4d2 [Type: [...]]
+// cdb-command: dx o2
+// cdb-check:o2               : Some [Type: enum$<core::option::Option<u64> >]
+// cdb-check:    [variant]        : Some
+// cdb-check:    [+0x008] __0              : 0x162e [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx t1
+// cdb-check:t1               : (0xa, 0x14) [Type: tuple$<u32,u32>]
+// cdb-check:    [0]              : 0xa [Type: unsigned int]
+// cdb-check:    [1]              : 0x14 [Type: unsigned int]
+// cdb-command: dx t2
+// cdb-check:t2               : (0x1e, 0x28) [Type: tuple$<u64,u64>]
+// cdb-check:    [0]              : 0x1e [Type: unsigned __int64]
+// cdb-check:    [1]              : 0x28 [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s                : "this is a static str" [Type: str]
+// cdb-check:    [len]            : 0x14 [Type: unsigned [...]]
+// cdb-check:    [chars]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s                : { len=0x5 } [Type: slice$<u8>]
+// cdb-check:    [len]            : 0x5 [Type: unsigned [...]]
+// cdb-check:    [0]              : 0x1 [Type: unsigned char]
+// cdb-check:    [1]              : 0x2 [Type: unsigned char]
+// cdb-check:    [2]              : 0x3 [Type: unsigned char]
+// cdb-check:    [3]              : 0x4 [Type: unsigned char]
+// cdb-check:    [4]              : 0x5 [Type: unsigned char]
+
+use std::ops::Range;
+
+fn range(r1: Range<u32>, r2: Range<u64>) {
+    zzz(); // #break
+}
+
+fn range_mut(mut r1: Range<u32>, mut r2: Range<u64>) {
+    if r1.start == 9 {
+        r1.end = 100;
+    }
+
+    if r2.start == 12 {
+        r2.end = 90;
+    }
+
+    zzz(); // #break
+}
+
+fn option(o1: Option<u32>, o2: Option<u64>) {
+    zzz(); // #break
+}
+
+fn tuple(t1: (u32, u32), t2: (u64, u64)) {
+    zzz(); // #break
+}
+
+fn str(s: &str) {
+    zzz(); // #break
+}
+
+fn slice(s: &[u8]) {
+    zzz(); // #break
+}
+
+fn zzz() { }
+
+fn main() {
+    range(10..12, 20..30);
+    range_mut(9..20, 12..80);
+    option(Some(1234), Some(5678));
+    tuple((10, 20), (30, 40));
+    str("this is a static str");
+    slice(&[1, 2, 3, 4, 5]);
+}
index 40bea30f1252ca853d300202ae31eeb532b206ae..4a529541bae60734236b0d380a72aa074a526fd0 100644 (file)
@@ -3,6 +3,8 @@
 // cdb-only
 // min-cdb-version: 10.0.21287.1005
 // compile-flags:-g
+// FIXME: Failed on update to 10.0.22000.1
+// ignore-windows
 
 // === CDB TESTS ==================================================================================
 //
index baeada69d1c9a2883ff095deed89c8fc9b5b4d6b..55a4ecc1c1a29fffa0a6cd5cc256990cb0db063f 100644 (file)
 // cdb-check:    [11]             : 33 '!' [Type: char]
 
 // cdb-command: dx os_string
-// cdb-check:os_string        : "IAMA OS string 😃" [Type: std::ffi::os_str::OsString]
+// NOTE: OSString is WTF-8 encoded which Windows debuggers don't understand. Verify the UTF-8
+//       portion displays correctly.
+// cdb-check:os_string        : "IAMA OS string [...]" [Type: std::ffi::os_str::OsString]
 // cdb-check:    [<Raw View>]     [Type: std::ffi::os_str::OsString]
-// cdb-check:    [chars]          : "IAMA OS string 😃"
+// cdb-check:    [chars]          : "IAMA OS string [...]"
 
 // cdb-command: dx some
 // cdb-check:some             : Some [Type: enum$<core::option::Option<i16> >]
 // cdb-check:    [variant]        : None
 
 // cdb-command: dx some_string
-// NOTE: cdb fails to interpret debug info of Option enums on i686.
-// cdb-check:some_string      [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:some_string      :  Some({...}) [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:    [<Raw View>]     [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:    [variant]        :  Some
+// cdb-check:    [+0x000] __0              : "IAMA optional string!" [Type: alloc::string::String]
 
 // cdb-command: dx linkedlist
 // cdb-check:linkedlist       : { len=0x2 } [Type: alloc::collections::linked_list::LinkedList<i32>]
index 9b3b381d6210ac4f81b73721bc00fa01054c850a..dd3dce4e7209c746dfd49a479156ae8b6b23b060 100644 (file)
@@ -1,9 +1,15 @@
-// revisions: rpass1 rpass2
+// revisions: rpass1 rpass2 rpass3 rpass4
 // compile-flags: -Zquery-dep-graph
+// [rpass1]compile-flags: -Zincremental-ignore-spans
+// [rpass2]compile-flags: -Zincremental-ignore-spans
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 #![feature(rustc_attrs)]
-#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
 #![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass4")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass4")]
 
 // This test case makes sure that a change in symbol visibility is detected by
 // our dependency tracking. We do this by changing a module's visibility to
 // even from an executable. Plain Rust functions are only exported from Rust
 // libraries, which our test infrastructure does not support.
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1,rpass3))]
 pub mod mod1 {
     #[no_mangle]
     pub fn foo() {}
 }
 
-#[cfg(rpass2)]
+#[cfg(any(rpass2,rpass4))]
 mod mod1 {
     #[no_mangle]
     pub fn foo() {}
index d4201400f0fc697152f103ef29dbb3301fca7f8c..648f71f9230c3b3b7abe384e2cdbf81169907786 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 
 #![allow(warnings)]
@@ -19,14 +25,16 @@ fn callee2(_x: u32, _y: i64) {}
 
 
 // Change Callee (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_callee_function() {
     callee1(1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_callee_function() {
     callee2(1, 2)
 }
@@ -34,14 +42,16 @@ pub fn change_callee_function() {
 
 
 // Change Argument (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_function() {
     callee1(1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_function() {
     callee1(1, 3)
 }
@@ -50,13 +60,15 @@ pub fn change_argument_function() {
 
 // Change Callee Indirectly (Function)
 mod change_callee_indirectly_function {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::callee1 as callee;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::callee2 as callee;
 
     #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_callee_indirectly_function() {
         callee(1, 2)
     }
@@ -70,15 +82,17 @@ fn method2(&self, _x: char, _y: bool) {}
 }
 
 // Change Callee (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_callee_method() {
     let s = Struct;
     s.method1('x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_callee_method() {
     let s = Struct;
     s.method2('x', true);
@@ -87,15 +101,17 @@ pub fn change_callee_method() {
 
 
 // Change Argument (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_method() {
     let s = Struct;
     s.method1('x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_method() {
     let s = Struct;
     s.method1('y', true);
@@ -104,15 +120,17 @@ pub fn change_argument_method() {
 
 
 // Change Callee (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
     Struct::method2(&s, 'x', true);
@@ -121,32 +139,36 @@ pub fn change_ufcs_callee_method() {
 
 
 // Change Argument (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
-    Struct::method1(&s, 'x', false);
+    Struct::method1(&s, 'x',false);
 }
 
 
 
 // Change To UFCS
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_to_ufcs() {
     let s = Struct;
-    s.method1('x', true);
+    s.method1('x', true); // ------
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 // One might think this would be expanded in the hir_owner_nodes/Mir, but it actually
 // results in slightly different hir_owner/Mir.
 pub fn change_to_ufcs() {
@@ -162,15 +184,15 @@ fn method1(&self, _x: char, _y: bool) {}
 
 // Change UFCS Callee Indirectly
 pub mod change_ufcs_callee_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Struct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Struct2 as Struct;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
-
-
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_ufcs_callee_indirectly() {
         let s = Struct;
         Struct::method1(&s, 'q', false)
index 4a00a6c72f79ea2572b4b29bca8eea9e8b931b15..2a4306fc17c2d9406a9df9c5acc0c9ff7adb70f6 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 
 // Change closure body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_closure_body() {
     let _ = || 1u32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_closure_body() {
     let _ = || 3u32;
 }
@@ -30,15 +38,17 @@ pub fn change_closure_body() {
 
 
 // Add parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_parameter() {
     let x = 0u32;
-    let _ = || x + 1;
+    let _ = |      | x + 1;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_parameter() {
     let x = 0u32;
     let _ = |x: u32| x + 1;
@@ -47,14 +57,16 @@ pub fn add_parameter() {
 
 
 // Change parameter pattern
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_parameter_pattern() {
-    let _ = |x: (u32,)| x;
+    let _ = | x  : (u32,)| x;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_parameter_pattern() {
     let _ = |(x,): (u32,)| x;
 }
@@ -62,14 +74,16 @@ pub fn change_parameter_pattern() {
 
 
 // Add `move` to closure
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_move() {
-    let _ = || 1;
+    let _ =      || 1;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_move() {
     let _ = move || 1;
 }
@@ -77,15 +91,17 @@ pub fn add_move() {
 
 
 // Add type ascription to parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_type_ascription_to_parameter() {
-    let closure = |x| x + 1u32;
+    let closure = |x     | x + 1u32;
     let _: u32 = closure(1);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
     let _: u32 = closure(1);
@@ -94,15 +110,17 @@ pub fn add_type_ascription_to_parameter() {
 
 
 // Change parameter type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_parameter_type() {
     let closure = |x: u32| (x as u64) + 1;
     let _ = closure(1);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
     let _ = closure(1);
index 6e0db6a49aae2054db9aa0e27cec564c90491764..c85f0bbecdb3928bacb3afe2e5f33d66fe85bfeb 100644 (file)
@@ -7,7 +7,7 @@
 
 // build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index 26ff6b109dc326f2703462523cf07418d32114fb..7522fa5a0260c4ce30625781a5896f08a7b8d817 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -24,7 +30,7 @@ pub enum Enum {
 }
 
 // Change field value (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
@@ -33,9 +39,11 @@ pub fn change_field_value_struct_like() -> Enum {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
@@ -47,7 +55,7 @@ pub fn change_field_value_struct_like() -> Enum {
 
 
 // Change field order (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         x: 3,
@@ -56,9 +64,11 @@ pub fn change_field_order_struct_like() -> Enum {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
 pub fn change_field_order_struct_like() -> Enum {
@@ -86,18 +96,20 @@ pub enum Enum2 {
 }
 
 // Change constructor path (struct-like) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_struct_like() {
-    let _ = Enum::Struct {
+    let _ = Enum ::Struct {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
@@ -109,18 +121,20 @@ pub fn change_constructor_path_struct_like() {
 
 
 // Change variant (regular struct) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_struct_like() {
-    let _ = Enum2::Struct {
+    let _ = Enum2::Struct  {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
         x: 0,
@@ -132,9 +146,9 @@ pub fn change_constructor_variant_struct_like() {
 
 // Change constructor path indirectly (struct-like) -------------------------
 pub mod change_constructor_path_indirectly_struct_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2 as TheEnum;
 
     #[rustc_clean(
@@ -143,6 +157,12 @@ pub mod change_constructor_path_indirectly_struct_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::Struct {
             x: 0,
@@ -156,13 +176,15 @@ pub fn function() -> TheEnum {
 // Change constructor variant indirectly (struct-like) ---------------------------
 pub mod change_constructor_variant_indirectly_struct_like {
     use super::Enum2;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum2::Struct as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2::Struct2 as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Enum2 {
         Variant {
             x: 0,
@@ -174,14 +196,16 @@ pub fn function() -> Enum2 {
 
 
 // Change field value (tuple-like) -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
 }
@@ -189,17 +213,22 @@ pub fn change_field_value_tuple_like() -> Enum {
 
 
 // Change constructor path (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_tuple_like() {
-    let _ = Enum::Tuple(0, 1, 2);
+    let _ = Enum ::Tuple(0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg="cfail2",
     except="hir_owner_nodes,optimized_mir,typeck"
 )]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+    cfg="cfail5",
+    except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
@@ -207,17 +236,22 @@ pub fn change_constructor_path_tuple_like() {
 
 
 // Change constructor variant (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_tuple_like() {
-    let _ = Enum2::Tuple(0, 1, 2);
+    let _ = Enum2::Tuple (0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg="cfail2",
     except="hir_owner_nodes,optimized_mir,typeck"
 )]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+    cfg="cfail5",
+    except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple2(0, 1, 2);
 }
@@ -225,9 +259,9 @@ pub fn change_constructor_variant_tuple_like() {
 
 // Change constructor path indirectly (tuple-like) ---------------------------
 pub mod change_constructor_path_indirectly_tuple_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2 as TheEnum;
 
     #[rustc_clean(
@@ -236,6 +270,12 @@ pub mod change_constructor_path_indirectly_tuple_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::Tuple(0, 1, 2)
     }
@@ -246,13 +286,15 @@ pub fn function() -> TheEnum {
 // Change constructor variant indirectly (tuple-like) ---------------------------
 pub mod change_constructor_variant_indirectly_tuple_like {
     use super::Enum2;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum2::Tuple as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2::Tuple2 as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
     }
@@ -272,14 +314,16 @@ pub enum Clike2 {
 }
 
 // Change constructor path (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_c_like() {
-    let _x = Clike::B;
+    let _x = Clike ::B;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_c_like() {
     let _x = Clike2::B;
 }
@@ -287,14 +331,16 @@ pub fn change_constructor_path_c_like() {
 
 
 // Change constructor variant (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::A;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::C;
 }
@@ -302,9 +348,9 @@ pub fn change_constructor_variant_c_like() {
 
 // Change constructor path indirectly (C-like) ---------------------------
 pub mod change_constructor_path_indirectly_c_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Clike as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Clike2 as TheEnum;
 
     #[rustc_clean(
@@ -313,6 +359,12 @@ pub mod change_constructor_path_indirectly_c_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::B
     }
@@ -323,13 +375,15 @@ pub fn function() -> TheEnum {
 // Change constructor variant indirectly (C-like) ---------------------------
 pub mod change_constructor_variant_indirectly_c_like {
     use super::Clike;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Clike::A as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Clike::B as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Clike {
         Variant
     }
index 76bff3cad3882b56f63c85242941680da0ba21a5..ab9c740844b8fd3967b28fd69d8a3461fda9f2d0 100644 (file)
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 
 // Change enum visibility -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumVisibility { A }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub enum EnumVisibility {
     A
 }
@@ -35,15 +43,17 @@ pub enum EnumVisibility {
 
 
 // Change name of a c-style variant -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameCStyleVariant {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameCStyleVariant {
     Variant1,
     Variant2Changed,
@@ -52,15 +62,17 @@ enum EnumChangeNameCStyleVariant {
 
 
 // Change name of a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
     Variant2Changed(u32, f32),
@@ -69,15 +81,17 @@ enum EnumChangeNameTupleStyleVariant {
 
 
 // Change name of a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
     Variant2Changed { a: u32, b: f32 },
@@ -86,31 +100,33 @@ enum EnumChangeNameStructStyleVariant {
 
 
 // Change the value of a c-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
     Variant2 = 11,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
-
-    Variant2 =
-        22,
+    Variant2 = 22,
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
     Variant2 = 11,
@@ -119,14 +135,16 @@ enum EnumChangeValueCStyleVariant1 {
 
 
 // Add a c-style variant ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddCStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddCStyleVariant {
     Variant1,
     Variant2,
@@ -135,15 +153,17 @@ enum EnumAddCStyleVariant {
 
 
 // Remove a c-style variant ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveCStyleVariant {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveCStyleVariant {
     Variant1,
 }
@@ -151,14 +171,16 @@ enum EnumRemoveCStyleVariant {
 
 
 // Add a tuple-style variant --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTupleStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
@@ -167,15 +189,17 @@ enum EnumAddTupleStyleVariant {
 
 
 // Remove a tuple-style variant -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
 }
@@ -183,14 +207,16 @@ enum EnumRemoveTupleStyleVariant {
 
 
 // Add a struct-style variant -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddStructStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
@@ -199,15 +225,17 @@ enum EnumAddStructStyleVariant {
 
 
 // Remove a struct-style variant ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveStructStyleVariant {
     Variant1,
 }
@@ -215,14 +243,16 @@ enum EnumRemoveStructStyleVariant {
 
 
 // Change the type of a field in a tuple-style variant ------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32, u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32,
         u64),
@@ -231,15 +261,17 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 
 
 // Change the type of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
     Variant2 {
@@ -251,14 +283,16 @@ enum EnumChangeFieldTypeStructStyleVariant {
 
 
 // Change the name of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, c: u32 },
 }
@@ -266,14 +300,16 @@ enum EnumChangeFieldNameStructStyleVariant {
 
 
 // Change order of fields in a tuple-style variant ----------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(u32, u64),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(
         u64,
@@ -283,14 +319,16 @@ enum EnumChangeOrderTupleStyleVariant {
 
 
 // Change order of fields in a struct-style variant ---------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { b: f32, a: u32 },
 }
@@ -298,14 +336,16 @@ enum EnumChangeFieldOrderStructStyleVariant {
 
 
 // Add a field to a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32, u32),
 }
@@ -313,14 +353,16 @@ enum EnumAddFieldTupleStyleVariant {
 
 
 // Add a field to a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32, c: u32 },
 }
@@ -328,15 +370,17 @@ enum EnumAddFieldStructStyleVariant {
 
 
 // Add #[must_use] to the enum ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddMustUse {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[must_use]
 enum EnumAddMustUse {
     Variant1,
@@ -346,15 +390,17 @@ enum EnumAddMustUse {
 
 
 // Add #[repr(C)] to the enum -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddReprC {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="type_of")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(C)]
 enum EnumAddReprC {
     Variant1,
@@ -364,14 +410,16 @@ enum EnumAddReprC {
 
 
 // Change the name of a type parameter ----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameOfTypeParameter<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameOfTypeParameter<T> {
     Variant1(T),
 }
@@ -379,15 +427,17 @@ enum EnumChangeNameOfTypeParameter<T> {
 
 
 // Add a type parameter ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTypeParameter<S> {
     Variant1(S),
     Variant2(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTypeParameter<S, T> {
     Variant1(S),
     Variant2(T),
@@ -396,14 +446,16 @@ enum EnumAddTypeParameter<S, T> {
 
 
 // Change the name of a lifetime parameter ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameOfLifetimeParameter<'a> {
     Variant1(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameOfLifetimeParameter<'b> {
     Variant1(&'b u32),
 }
@@ -411,15 +463,17 @@ enum EnumChangeNameOfLifetimeParameter<'b> {
 
 
 // Add a lifetime parameter ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameter<'a> {
     Variant1(&'a u32),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameter<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
@@ -428,30 +482,34 @@ enum EnumAddLifetimeParameter<'a, 'b> {
 
 
 // Add a lifetime bound to a lifetime parameter -------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameterBound<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
 // Add a lifetime bound to a type parameter -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeBoundToParameter<'a, T> {
     Variant1(T),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
     Variant1(T),
     Variant2(&'a u32),
@@ -460,14 +518,16 @@ enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
 
 
 // Add a trait bound to a type parameter --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTraitBound<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTraitBound<T: Sync> {
     Variant1(T),
 }
@@ -475,15 +535,17 @@ enum EnumAddTraitBound<T: Sync> {
 
 
 // Add a lifetime bound to a lifetime parameter in where clause ---------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
     Variant1(&'a u32),
     Variant2(&'b u32),
@@ -492,15 +554,17 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
 
 
 // Add a lifetime bound to a type parameter in where clause -------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> {
     Variant1(T),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
     Variant1(T),
     Variant2(&'a u32),
@@ -509,14 +573,16 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
 
 
 // Add a trait bound to a type parameter in where clause ----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTraitBoundWhere<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTraitBoundWhere<T> where T: Sync {
     Variant1(T),
 }
@@ -524,15 +590,17 @@ enum EnumAddTraitBoundWhere<T> where T: Sync {
 
 
 // In an enum with two variants, swap usage of type parameters ----------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 { a: A },
     Variant2 { a: B },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 {
         a: B
@@ -545,15 +613,17 @@ enum EnumSwapUsageTypeParameters<A, B> {
 
 
 // In an enum with two variants, swap usage of lifetime parameters ------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 { a: &'a u32 },
     Variant2 { b: &'b u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 {
         a: &'b u32
@@ -572,13 +642,15 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> {
 
 // Change field type in tuple-style variant indirectly by modifying a use statement
 mod change_field_type_indirectly_tuple_style {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail6")]
     enum TupleStyle {
         Variant1(
             FieldType
@@ -590,13 +662,15 @@ enum TupleStyle {
 
 // Change field type in record-style variant indirectly by modifying a use statement
 mod change_field_type_indirectly_struct_style {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail6")]
     enum StructStyle {
         Variant1 {
             a: FieldType
@@ -613,13 +687,15 @@ trait ReferencedTrait2 {}
 
 // Change trait bound of type parameter indirectly by modifying a use statement
 mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     enum Enum<T: Trait> {
         Variant1(T)
     }
@@ -629,13 +705,15 @@ enum Enum<T: Trait> {
 
 // Change trait bound of type parameter in where clause indirectly by modifying a use statement
 mod change_trait_bound_indirectly_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     enum Enum<T> where T: Trait {
         Variant1(T)
     }
index 40b6925bc72769ff8ded2221e620314fa212c5da..d5fb8a2e53437a118e03c66aa14dbcaa77f8c74f 100644 (file)
@@ -1,6 +1,12 @@
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 //         the hash of the hir_owner_nodes node should change, but not the hash of
 //         either the hir_owner or the Metadata node.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn body_not_exported_to_metadata() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
 }
@@ -28,15 +36,17 @@ pub fn body_not_exported_to_metadata() -> u32 {
 //         marked as #[inline]. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
     2
@@ -48,15 +58,17 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 //         generic. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
     2
index 1160bc376c49a182296ec26f99496eac7b9c79c2..4bc98fd7cd08291f2e424120389383817d4882e3 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type = "rlib"]
 
 // Change function name --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_function_name1(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_function_name2(c: i64) -> i32;
 }
 
 // Change parameter name -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_parameter_name(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
 // Change parameter type -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_parameter_type(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
 // Change return type ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_return_type(c: i32) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
-    pub fn change_return_type(c: i32) -> i8;
+    pub fn change_return_type(c: i32) -> i8 ;
 }
 
 // Add parameter ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn add_parameter(c: i32) -> i32;
+    pub fn add_parameter(c: i32        ) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
 // Add return type -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn add_return_type(c: i32);
+    pub fn add_return_type(c: i32)       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_return_type(c: i32) -> i32;
 }
 
 // Make function variadic ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn make_function_variadic(c: i32);
+    pub fn make_function_variadic(c: i32     );
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn make_function_variadic(c: i32, ...);
 }
 
 // Change calling convention ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_calling_convention(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "rust-call" {
     pub fn change_calling_convention(c: i32);
 }
 
 // Make function public --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    fn make_function_public(c: i32);
+    fn     make_function_public(c: i32);
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn make_function_public(c: i32);
 }
 
 // Add function ----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn add_function1(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_function1(c: i32);
     pub fn add_function2();
 }
 
 // Change link-name ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[link(name = "foo")]
 extern "C" {
     pub fn change_link_name(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[link(name = "bar")]
 extern "C" {
     pub fn change_link_name(c: i32);
 
 // Indirectly change parameter type --------------------------------------------
 mod indirectly_change_parameter_type {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::c_i32 as c_int;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::c_i64 as c_int;
 
     #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5")]
+    #[rustc_clean(cfg = "cfail6")]
     extern "C" {
         pub fn indirectly_change_parameter_type(c: c_int);
     }
@@ -179,13 +209,15 @@ mod indirectly_change_parameter_type {
 
 // Indirectly change return type --------------------------------------------
 mod indirectly_change_return_type {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::c_i32 as c_int;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::c_i64 as c_int;
 
     #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5")]
+    #[rustc_clean(cfg = "cfail6")]
     extern "C" {
         pub fn indirectly_change_return_type() -> c_int;
     }
index e1460503d2d9424d0a0adf515ef7cf1e40342c72..5a944d28a0b913facc8955e2f829a7d50dcbce42 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -38,7 +46,7 @@ pub fn change_loop_body() {
 
 
 // Change iteration variable name ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _i in 0..1 {
@@ -47,9 +55,11 @@ pub fn change_iteration_variable_name() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _a in 0..1 {
@@ -61,18 +71,20 @@ pub fn change_iteration_variable_name() {
 
 
 // Change iteration variable pattern -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
-    for _i in &[0, 1, 2] {
+    for  _i in &[0, 1, 2] {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck, promoted_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
     for &_i in &[0, 1, 2] {
@@ -84,7 +96,7 @@ pub fn change_iteration_variable_pattern() {
 
 
 // Change iterable -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 2] {
@@ -93,9 +105,11 @@ pub fn change_iterable() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 3] {
@@ -107,17 +121,20 @@ pub fn change_iterable() {
 
 
 // Add break -------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -129,18 +146,20 @@ pub fn add_break() {
 
 
 // Add loop label --------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    for _ in 0..1 {
+            for _ in 0..1 {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -152,18 +171,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -175,7 +196,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -186,9 +207,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -202,18 +225,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -225,7 +250,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -236,9 +261,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -252,7 +279,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -261,13 +288,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
-        break;
+        break   ;
     }
 }
index c8530c70f78d2086e9ae31de93e8d8e1ab3738ec..4124eada188e862e990fc5e3d930c084ba8855c0 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(linkage)]
 
 // Add Parameter ---------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_parameter() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_parameter(p: i32) {}
 
 // Add Return Type -------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn add_return_type() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn add_return_type()       {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_return_type() -> () {}
 
 // Change Parameter Type -------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_of_parameter(p: i32) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_of_parameter(p: i64) {}
 
 // Change Parameter Type Reference ---------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_of_parameter_ref(p: &i32) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
 // Change Parameter Order ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn order_of_parameters(p1: i32, p2: i64) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
 // Unsafe ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn make_unsafe() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub unsafe fn make_unsafe() {}
 
 // Extern ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn make_extern() {}
+#[cfg(any(cfail1,cfail4))]
+pub            fn make_extern() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
 pub extern "C" fn make_extern() {}
 
 // Type Parameter --------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn type_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn type_parameter   () {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_parameter<T>() {}
 
 // Lifetime Parameter ----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn lifetime_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn lifetime_parameter    () {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn lifetime_parameter<'a>() {}
 
 // Trait Bound -----------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn trait_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn trait_bound<T    >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn trait_bound<T: Eq>() {}
 
 // Builtin Bound ---------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn builtin_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn builtin_bound<T      >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn builtin_bound<T: Send>() {}
 
 // Lifetime Bound --------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn lifetime_bound<'a, T>() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn lifetime_bound<'a, T: 'a>() {}
 
 // Second Trait Bound ----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_trait_bound<T: Eq>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_trait_bound<T: Eq        >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_trait_bound<T: Eq + Clone>() {}
 
 // Second Builtin Bound --------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_builtin_bound<T: Send>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_builtin_bound<T: Send        >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn second_builtin_bound<T: Send + Sized>() {}
 
 // Second Lifetime Bound -------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_lifetime_bound<'a, 'b, T: 'a     >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
 // Inline ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn inline() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[inline]
 pub fn inline() {}
 
 // Inline Never ----------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline(always)]
 pub fn inline_never() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[inline(never)]
 pub fn inline_never() {}
 
 // No Mangle -------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn no_mangle() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[no_mangle]
 pub fn no_mangle() {}
 
 // Linkage ---------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn linkage() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[linkage = "weak_odr"]
 pub fn linkage() {}
 
 // Return Impl Trait -----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn return_impl_trait() -> i32 {
+#[cfg(any(cfail1,cfail4))]
+pub fn return_impl_trait() -> i32        {
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn return_impl_trait() -> impl Clone {
     0
 }
 
 // Change Return Impl Trait ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_return_impl_trait() -> impl Clone {
     0u32
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
-pub fn change_return_impl_trait() -> impl Copy {
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn change_return_impl_trait() -> impl  Copy {
     0u32
 }
 
@@ -267,9 +335,9 @@ pub fn change_return_impl_trait() -> impl Copy {
 pub struct ReferencedType2;
 
 pub mod change_return_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as ReturnType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as ReturnType;
 
     #[rustc_clean(
@@ -277,6 +345,11 @@ pub mod change_return_type_indirectly {
         except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(
+        cfg = "cfail5",
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+    )]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
     }
@@ -285,9 +358,9 @@ pub fn indirect_return_type() -> ReturnType {
 // Change Parameter Type Indirectly --------------------------------------------
 
 pub mod change_parameter_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as ParameterType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as ParameterType;
 
     #[rustc_clean(
@@ -295,6 +368,11 @@ pub mod change_parameter_type_indirectly {
         except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(
+        cfg = "cfail5",
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+    )]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
 
@@ -304,26 +382,30 @@ pub trait ReferencedTrait1 {}
 pub trait ReferencedTrait2 {}
 
 pub mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
 
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 
 pub mod change_trait_bound_indirectly_in_where_clause {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_trait_bound_where<T>(p: T)
     where
         T: Trait,
index ddae9c9f03256473dc1860c578336276f7e9a02c..0c5e73b01077ab593e99d1f1040247691477c936 100644 (file)
@@ -6,27 +6,34 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change condition (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_condition(x: bool) -> u32 {
-    if x {
+    if  x {
         return 1
     }
 
     return 0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
         return 1
@@ -36,7 +43,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 // Change then branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
         return 1
@@ -45,9 +52,11 @@ pub fn change_then_branch(x: bool) -> u32 {
     return 0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
         return 2
@@ -59,7 +68,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 
 
 // Change else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
         1
@@ -68,9 +77,11 @@ pub fn change_else_branch(x: bool) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
         1
@@ -82,20 +93,23 @@ pub fn change_else_branch(x: bool) -> u32 {
 
 
 // Add else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
 
     if x {
         ret = 2;
+    /*----*/
     }
 
     ret
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
 
@@ -110,7 +124,7 @@ pub fn add_else_branch(x: bool) -> u32 {
 
 
 // Change condition (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_x) = x {
         return 1
@@ -119,11 +133,13 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
-    if let Some(_) = x {
+    if let Some(_ ) = x {
         return 1
     }
 
@@ -133,18 +149,20 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 
 
 // Change then branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
-        return x
+        return x //-
     }
 
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         return x + 1
@@ -156,7 +174,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 
 
 // Change else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         x
@@ -165,9 +183,11 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         x
@@ -179,20 +199,23 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 
 
 // Add else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
 
     if let Some(x) = x {
         ret = x;
+    /*----*/
     }
 
     ret
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
 
index 49ee7a9cac091b2453deb87b33b0c4c99b8c406c..0532f4a0fd65db696327aae877383a683ccd6eb4 100644 (file)
@@ -6,22 +6,30 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change simple index
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[3]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[4]
 }
@@ -29,14 +37,16 @@ fn change_simple_index(slice: &[u32]) -> u32 {
 
 
 // Change lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..5]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[2..5]
 }
@@ -44,14 +54,16 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] {
 
 
 // Change upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..5]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -59,14 +71,16 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] {
 
 
 // Add lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
-    &slice[..4]
+    &slice[ ..4]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..4]
 }
@@ -74,14 +88,16 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] {
 
 
 // Add upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
-    &slice[3..]
+    &slice[3.. ]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -89,29 +105,33 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] {
 
 
 // Change mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_mutability(slice: &mut [u32]) -> u32 {
     (&mut slice[3..5])[0]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_mutability(slice: &mut [u32]) -> u32 {
-    (&slice[3..5])[0]
+    (&    slice[3..5])[0]
 }
 
 
 
 // Exclusive to inclusive range
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
-    &slice[3..7]
+    &slice[3.. 7]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
     &slice[3..=7]
 }
index 284a95f1a68b627fff0f3fc14a246e738ed335d4..3a59377e819694d12d946cbfd1d64a0d99b6e6e0 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 
 #![allow(warnings)]
 pub struct Foo;
 
 // Change Method Name -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
     pub fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_name2() { }
 }
 
 // Change Method Body -----------------------------------------------------------
 //
 // This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn method_body() { }
+    //--------------------------------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn method_body() {
+        // -----------------------
+    }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_body() {
         println!("Hello, world!");
     }
@@ -56,21 +72,40 @@ pub fn method_body() {
 // Change Method Body (inlined) ------------------------------------------------
 //
 // This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //------------------------------------------------------------
+    //
+    //--------------------------
     #[inline]
-    pub fn method_body_inlined() { }
+    pub fn method_body_inlined() {
+        // -----------------------
+    }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     pub fn method_body_inlined() {
         println!("Hello, world!");
@@ -79,146 +114,209 @@ pub fn method_body_inlined() {
 
 
 // Change Method Privacy -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------
+    //--------------------------
     pub fn method_privacy() { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
-    fn method_privacy() { }
+    #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail6")]
+    fn     method_privacy() { }
 }
 
 // Change Method Selfness -----------------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //---------------------------------------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //---------------------------------------------------------------------------------------------
+    //
+    //--------------------------
     pub fn method_selfness() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_selfness(&self) { }
 }
 
 // Change Method Selfmutness ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn method_selfmutness(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn method_selfmutness(&    self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_selfmutness(&mut self) { }
 }
 
 
 
 // Add Method To Impl ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
     pub fn add_method_to_impl1(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_to_impl1(&self) { }
 
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_to_impl2(&self) { }
 }
 
 
 
 // Add Method Parameter --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn add_method_parameter(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn add_method_parameter(&self        ) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_parameter(&self, _: i32) { }
 }
 
 
 
 // Change Method Parameter Name ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_parameter_name(&self, a: i64) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
 
 
 
 // Change Method Return Type ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_return_type(&self) -> u16 { 0 }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
-    pub fn change_method_return_type(&self) -> u8 { 0 }
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
+    pub fn change_method_return_type(&self) -> u32 { 0 }
 }
 
 
 
 // Make Method #[inline] -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //-------
     pub fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     pub fn make_method_inline(&self) -> u8 { 0 }
 }
@@ -226,85 +324,129 @@ pub fn make_method_inline(&self) -> u8 { 0 }
 
 
 //  Change order of parameters -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
 
 
 
 // Make method unsafe ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn make_method_unsafe(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub        fn make_method_unsafe(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub unsafe fn make_method_unsafe(&self) { }
 }
 
 
 
 // Make method extern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn make_method_extern(&self) { }
+    //----------------------------------------------------------------------------
+    //--------------------------
+    //----------------------------------------------------------------------------
+    //--------------------------
+    pub            fn make_method_extern(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub extern "C" fn make_method_extern(&self) { }
 }
 
 
 
 // Change method calling convention --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub extern "C" fn change_method_calling_convention(&self) { }
+    //----------------------------------------------------------------------------
+    //--------------------------
+    //----------------------------------------------------------------------------
+    //--------------------------
+    pub extern "C"      fn change_method_calling_convention(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub extern "system" fn change_method_calling_convention(&self) { }
 }
 
 
 
 // Add Lifetime Parameter to Method --------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ---------------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------
+    // -------------------------------------------------------
+    // --------------------------------------------------------
+    // ----------------------------------------------------------
+    // -----------------------------------------------------------
+    // ----------------------------------------------------------
+    // --------------------------------------------------------------------
+    // -------------------------
+    // --------------------------------------------------------------------------------
+    // -------------------------
+    pub fn add_lifetime_parameter_to_method    (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of lifetime parameters that don't
@@ -317,20 +459,43 @@ impl Foo {
     // `typeck` appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
 
 
 
 // Add Type Parameter To Method ------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_type_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ---------------------------------------------------------------
+    // -------------------------------------------------------------
+    // -----------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------
+    //
+    // -------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------
+    //
+    // -------------------------
+    pub fn add_type_parameter_to_method   (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of type parameters that don't appear in
@@ -346,40 +511,83 @@ impl Foo {
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_type_parameter_to_method<T>(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Lifetime Parameter of Method --------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //-----------------------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //-----------------------------------------------------------------------------
+    //
+    //--------------------------
+    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b    >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_bound_to_type_param_of_method<'a, T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------------
+    // -------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------------
+    //
+    // -------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------------
+    //
+    // -------------------------
+    pub fn add_lifetime_bound_to_type_param_of_method<'a, T    >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
@@ -390,23 +598,45 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\
-                                        type_of,fn_sig")]
+    #[rustc_clean(
+        cfg="cfail2",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
 }
 
 
 
 // Add Trait Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_trait_bound_to_type_param_of_method<T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------------
+    // -------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    pub fn add_trait_bound_to_type_param_of_method<T       >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
@@ -419,23 +649,34 @@ impl Foo {
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
 }
 
 
 
 // Add #[no_mangle] to Method --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //----------
     pub fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[no_mangle]
     pub fn add_no_mangle_to_method(&self) { }
 }
@@ -445,71 +686,90 @@ pub fn add_no_mangle_to_method(&self) { }
 struct Bar<T>(T);
 
 // Add Type Parameter To Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Bar<u32> {
     pub fn add_type_parameter_to_impl(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")]
+#[rustc_clean(cfg="cfail6")]
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
         except="generics_of,fn_sig,typeck,type_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="generics_of,fn_sig,typeck,type_of,optimized_mir"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_type_parameter_to_impl(&self) { }
 }
 
 
 
 // Change Self Type of Impl ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Bar<u32> {
     pub fn change_impl_self_type(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
 impl Bar<u64> {
     #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_impl_self_type(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> Bar<T> {
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: 'static> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
 
 
 
 // Add Trait Bound to Impl Parameter -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> Bar<T> {
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: Clone> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
 
@@ -518,12 +778,12 @@ pub fn add_trait_bound_to_impl_parameter(&self) { }
 pub fn instantiation_root() {
     Foo::method_privacy();
 
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     {
         Bar(0u32).change_impl_self_type();
     }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     {
         Bar(0u64).change_impl_self_type();
     }
index 7fd9975bc22a93366d1840596c2977a598ea060c..a5d53258a7bd007fba5a131e4cc106cb31124395 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -17,7 +23,7 @@
 
 
 // Change template
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
     let c: i32;
@@ -32,9 +38,11 @@ pub fn change_template(a: i32) -> i32 {
     c
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
     let c: i32;
@@ -52,7 +60,7 @@ pub fn change_template(a: i32) -> i32 {
 
 
 // Change output
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
@@ -68,9 +76,11 @@ pub fn change_output(a: i32) -> i32 {
     _out1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
@@ -89,7 +99,7 @@ pub fn change_output(a: i32) -> i32 {
 
 
 // Change input
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -104,9 +114,11 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -124,7 +136,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 
 
 // Change input constraint
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -139,9 +151,11 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -159,7 +173,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 
 
 // Change clobber
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
     let _out;
@@ -167,16 +181,18 @@ pub fn change_clobber(_a: i32) -> i32 {
         llvm_asm!("add 1, $0"
                   : "=r"(_out)
                   : "0"(_a)
-                  :
+                  :/*--*/
                   :
                   );
     }
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
     let _out;
@@ -194,7 +210,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 
 
 // Change options
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
     let _out;
@@ -203,15 +219,17 @@ pub fn change_options(_a: i32) -> i32 {
                   : "=r"(_out)
                   : "0"(_a)
                   :
-                  :
+                  :/*-------*/
                   );
     }
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
     let _out;
index 918e72582d6978289c736000f5d769463f933372..a9f90ca9fed81ba359acddb381884fc9a473bfec 100644 (file)
@@ -6,24 +6,30 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change Name -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name() {
     let _x = 2u64;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name() {
     let _y = 2u64;
 }
@@ -31,15 +37,16 @@ pub fn change_name() {
 
 
 // Add Type --------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_type() {
-    let _x = 2u32;
+    let _x      = 2u32;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_type() {
     let _x: u32 = 2u32;
 }
@@ -47,31 +54,33 @@ pub fn add_type() {
 
 
 // Change Type -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_type() {
     let _x: u64 = 2;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_type() {
-    let _x: u8 = 2;
+    let _x: u8  = 2;
 }
 
 
 
 // Change Mutability of Reference Type -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_reference_type() {
-    let _x: &u64;
+    let _x: &    u64;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
 }
@@ -79,31 +88,33 @@ pub fn change_mutability_of_reference_type() {
 
 
 // Change Mutability of Slot ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_slot() {
     let mut _x: u64 = 0;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_slot() {
-    let _x: u64 = 0;
+    let     _x: u64 = 0;
 }
 
 
 
 // Change Simple Binding to Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_simple_binding_to_pattern() {
-    let _x = (0u8, 'x');
+    let  _x      = (0u8, 'x');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
 }
@@ -111,15 +122,16 @@ pub fn change_simple_binding_to_pattern() {
 
 
 // Change Name in Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_in_pattern() {
     let (_a, _b) = (1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
 }
@@ -127,15 +139,16 @@ pub fn change_name_in_pattern() {
 
 
 // Add `ref` in Pattern --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_ref_in_pattern() {
-    let (_a, _b) = (1u8, 'y');
+    let (    _a, _b) = (1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
 }
@@ -143,15 +156,16 @@ pub fn add_ref_in_pattern() {
 
 
 // Add `&` in Pattern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_amp_in_pattern() {
-    let (_a, _b) = (&1u8, 'y');
+    let ( _a, _b) = (&1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
 }
@@ -159,15 +173,16 @@ pub fn add_amp_in_pattern() {
 
 
 // Change Mutability of Binding in Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_binding_in_pattern() {
-    let (_a, _b) = (99u8, 'q');
+    let (    _a, _b) = (99u8, 'q');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
 }
@@ -175,15 +190,16 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 
 // Add Initializer -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_initializer() {
-    let _x: i16;
+    let _x: i16       ;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
 }
@@ -191,15 +207,16 @@ pub fn add_initializer() {
 
 
 // Change Initializer ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_initializer() {
     let _x = 4u16;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_initializer() {
     let _x = 5u16;
 }
index 178def016a25f0ed607100204add86289fa9f475..6fef31f5b32104ed758b7193ca62c759ec18c9c4 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     loop {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     loop {
@@ -38,17 +46,20 @@ pub fn change_loop_body() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     loop {
         _x = 1;
+        //----
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     loop {
@@ -60,18 +71,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    loop {
+    /*---*/ loop {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: loop {
@@ -83,18 +96,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
@@ -106,7 +121,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
@@ -117,9 +132,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
@@ -133,18 +150,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
@@ -156,7 +175,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
@@ -167,9 +186,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
@@ -183,7 +204,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
@@ -192,13 +213,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
         _x = 1;
-        break;
+        break   ;
     }
 }
index 969f930f57bdfb2f675b978fc199befd240a69fa..314461b5909f7e36292c313b7ed9c001b671d0db 100644 (file)
@@ -6,28 +6,35 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Add Arm ---------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_arm(x: u32) -> u32 {
     match x {
         0 => 0,
         1 => 1,
+        /*---*/
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -40,7 +47,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 
 // Change Order Of Arms --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -49,10 +56,11 @@ pub fn change_order_of_arms(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
         1 => 1,
@@ -64,19 +72,20 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 
 // Add Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
-        1 => 1,
+        1      => 1,
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
@@ -88,19 +97,20 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 
 // Change Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
-        1 if y => 1,
+        1 if  y => 1,
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
@@ -112,19 +122,20 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 
 // Add @-Binding ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
         1 => 1,
-        _ => x,
+            _ => x,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -136,7 +147,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 
 // Change Name of @-Binding ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -145,10 +156,11 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -160,18 +172,19 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 
 // Change Simple Binding To Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (0, 0) => 0,
-        a => 1,
+         a     => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (0, 0) => 0,
@@ -182,7 +195,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 
 // Change Name In Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (a, 0) => 0,
@@ -191,10 +204,11 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (b, 0) => 0,
@@ -206,18 +220,19 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 
 // Change Mutability Of Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
-        (a, 0) => 0,
+        (    a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (mut a, 0) => 0,
@@ -228,18 +243,19 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 
 // Add `ref` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
-        (a, 0) => 0,
+        (    a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (ref a, 0) => 0,
@@ -250,18 +266,19 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 
 // Add `&` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
-        (a, 0) => 0,
+        ( a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
         (&a, 0) => 0,
@@ -272,7 +289,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 
 // Change RHS Of Arm -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -281,10 +298,11 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -296,19 +314,20 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 
 // Add Alternative To Arm ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
-        0 => 0,
+        0     => 0,
         1 => 1,
         _ => 2,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
         0 | 7 => 0,
index 6f4089c60fe23669209d847ff5ec1f121d8d22a9..2b2658b2f5f07b8f2107deb8535ab5c40fb24541 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 
 // Change static visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_VISIBILITY: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub static STATIC_VISIBILITY: u8 = 0;
 
 
 // Change static mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_MUTABILITY: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static mut STATIC_MUTABILITY: u8 = 0;
 
 
 // Add linkage attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_LINKAGE: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[linkage="weak_odr"]
 static STATIC_LINKAGE: u8 = 0;
 
 
 // Add no_mangle attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_NO_MANGLE: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[no_mangle]
 static STATIC_NO_MANGLE: u8 = 0;
 
 
 // Add thread_local attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_THREAD_LOCAL: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[thread_local]
 static STATIC_THREAD_LOCAL: u8 = 0;
 
 
 // Change type from i16 to u64
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_CHANGE_TYPE_1: i16 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_TYPE_1: u64 = 0;
 
 
 // Change type from Option<i8> to Option<u16>
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_CHANGE_TYPE_2: Option<i8> = None;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_TYPE_2: Option<u16> = None;
 
 
 // Change value between simple literals
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_1: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 2 }
 };
 
 // Change value between expressions
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_2: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 + 1 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 1 + 2 }
 };
 
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_3: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 2 + 3 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 2 * 3 }
 };
 
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_4: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 + 2 * 3 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 1 + 2 * 4 }
 };
 
 struct ReferencedType2;
 
 mod static_change_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as Type;
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as Type;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+    #[rustc_clean(cfg="cfail6")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+    #[rustc_clean(cfg="cfail6")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
index edec03d4f057e01556e4fad11b11db31a211e56a..6a62620463040da7c3de1cda89fe6776afa423a8 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -21,7 +27,7 @@ pub struct RegularStruct {
 }
 
 // Change field value (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
@@ -30,9 +36,11 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
@@ -44,7 +52,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 
 
 // Change field order (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 3,
@@ -53,9 +61,11 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         y: 4,
@@ -67,7 +77,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
 
 
 // Add field (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -77,13 +87,16 @@ pub fn add_field_regular_struct() -> RegularStruct {
 
     RegularStruct {
         x: 7,
+        // --
         .. struct1
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -101,7 +114,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 
 
 // Change field label (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -116,9 +129,11 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -142,18 +157,20 @@ pub struct RegularStruct2 {
 }
 
 // Change constructor path (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_regular_struct() {
-    let _ = RegularStruct {
+    let _ = RegularStruct  {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
         x: 0,
@@ -166,9 +183,9 @@ pub fn change_constructor_path_regular_struct() {
 
 // Change constructor path indirectly (regular struct)
 pub mod change_constructor_path_indirectly_regular_struct {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::RegularStruct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::RegularStruct2 as Struct;
 
     #[rustc_clean(
@@ -176,6 +193,11 @@ pub mod change_constructor_path_indirectly_regular_struct {
         except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Struct {
         Struct {
             x: 0,
@@ -190,14 +212,16 @@ pub fn function() -> Struct {
 pub struct TupleStruct(i32, i64, i16);
 
 // Change field value (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
 }
@@ -207,14 +231,16 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 pub struct TupleStruct2(u16, u16, u16);
 
 // Change constructor path (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_tuple_struct() {
-    let _ = TupleStruct(0, 1, 2);
+    let _ = TupleStruct (0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
 }
@@ -223,11 +249,16 @@ pub fn change_constructor_path_tuple_struct() {
 
 // Change constructor path indirectly (tuple struct)
 pub mod change_constructor_path_indirectly_tuple_struct {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::TupleStruct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::TupleStruct2 as Struct;
 
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     #[rustc_clean(
         cfg="cfail2",
         except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
index 0ce5aeaaf5028b43c79a28e48a245f7f8aec408c..b5d8a3ab34103d0d6380ae91cb46e2136a70ef65 100644 (file)
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Layout ----------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub struct LayoutPacked;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(packed)]
 pub struct LayoutPacked;
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct LayoutC;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(C)]
 struct LayoutC;
 
 
 // Tuple Struct Change Field Type ----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructFieldType(i32);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct TupleStructFieldType(
@@ -56,12 +67,14 @@ struct TupleStructFieldType(
 
 // Tuple Struct Add Field ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructAddField(i32);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct TupleStructAddField(
     i32,
     u32
@@ -70,23 +83,27 @@ struct TupleStructAddField(
 
 // Tuple Struct Field Visibility -----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructFieldVisibility(char);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct TupleStructFieldVisibility(pub char);
 
 
 // Record Struct Field Type ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldType { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct RecordStructFieldType {
@@ -96,23 +113,27 @@ struct RecordStructFieldType {
 
 // Record Struct Field Name ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldName { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructFieldName { y: f32 }
 
 
 // Record Struct Add Field -----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructAddField { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructAddField {
     x: f32,
     y: () }
@@ -120,12 +141,14 @@ struct RecordStructAddField {
 
 // Record Struct Field Visibility ----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldVisibility { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructFieldVisibility {
     pub x: f32
 }
@@ -133,34 +156,40 @@ struct RecordStructFieldVisibility {
 
 // Add Lifetime Parameter ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 
 
 // Add Lifetime Parameter Bound ------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameterBound<'a, 'b: 'a>(
     &'a f32,
     &'b f64
 );
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
     &'a f32,
     &'b f64)
@@ -169,12 +198,14 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
 
 // Add Type Parameter ----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameter<T1>(T1, T1);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameter<T1, T2>(
      // The field contains the parent's Generics, so it's dirty even though its
      // type hasn't changed.
@@ -185,23 +216,27 @@ struct AddTypeParameter<T1, T2>(
 
 // Add Type Parameter Bound ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameterBound<T>(T);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameterBound<T: Send>(
     T
 );
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameterBoundWhereClause<T>(T);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameterBoundWhereClause<T>(
     T
 ) where T: Sync;
@@ -214,17 +249,21 @@ struct AddTypeParameterBoundWhereClause<T>(
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub struct EmptyStruct;
 
 
 // Visibility ------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct Visibility;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub struct Visibility;
 
 struct ReferencedType1;
@@ -232,13 +271,15 @@ struct AddTypeParameterBoundWhereClause<T>(
 
 // Tuple Struct Change Field Type Indirectly -----------------------------------
 mod tuple_struct_change_field_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct TupleStruct(
         FieldType
     );
@@ -247,13 +288,15 @@ struct TupleStruct(
 
 // Record Struct Change Field Type Indirectly -----------------------------------
 mod record_struct_change_field_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct RecordStruct {
         _x: FieldType
     }
@@ -267,24 +310,28 @@ trait ReferencedTrait2 {}
 
 // Change Trait Bound Indirectly -----------------------------------------------
 mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct Struct<T: Trait>(T);
 }
 
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 mod change_trait_bound_indirectly_in_where_clause {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct Struct<T>(T) where T : Trait;
 }
index a604ca5ca82d71c5e25c3a2871d6389cb07c3bac..9cbd110d68aab76aafc5a413534330f5c15f2475 100644 (file)
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 
 // Change trait visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitVisibility { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait TraitVisibility { }
 
 
 
 // Change trait unsafety
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitUnsafety { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 unsafe trait TraitUnsafety { }
 
 
 
 // Add method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddMethod {
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait TraitAddMethod {
     fn method();
 }
@@ -57,14 +69,16 @@ pub trait TraitAddMethod {
 
 
 // Change name of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodName {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodName {
     fn methodChanged();
 }
@@ -72,157 +86,227 @@ trait TraitChangeMethodName {
 
 
 // Add return type to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddReturnType {
-    fn method();
+    //-----------------------------------------------------
+    //--------------------------
+    //-----------------------------------------------------
+    //--------------------------
+    fn method()       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddReturnType {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() -> u32;
 }
 
 
 
 // Change return type of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeReturnType {
+    // --------------------------------------------------------------------
+    // -------------------------
+    // --------------------------------------------------------------------
+    // -------------------------
     fn method() -> u32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeReturnType {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() -> u64;
 }
 
 
 
 // Add parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddParameterToMethod {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(      );
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddParameterToMethod {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: u32);
 }
 
 
 
 // Change name of method parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterName {
+    //------------------------------------------------------
+    //----------------------------------------------
+    //--------------------------
+    //----------------------------------------------
+    //--------------------------
     fn method(a: u32);
+
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     fn with_default(x: i32) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(b: u32);
 
     #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn with_default(y: i32) {}
 }
 
 
 
 // Change type of method parameter (i32 => i64)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterType {
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
     fn method(a: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterType {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: i64);
 }
 
 
 
 // Change type of method parameter (&i32 => &mut i32)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterTypeRef {
-    fn method(a: &i32);
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(a: &    i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterTypeRef {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: &mut i32);
 }
 
 
 
 // Change order of method parameters
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParametersOrder {
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
     fn method(a: i32, b: i64);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParametersOrder {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(b: i64, a: i32);
 }
 
 
 
 // Add default implementation to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddMethodAutoImplementation {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddMethodAutoImplementation {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() { }
 }
 
 
 
 // Change order of methods
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeOrderOfMethods {
     fn method0();
     fn method1();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeOrderOfMethods {
     fn method1();
     fn method0();
@@ -231,134 +315,198 @@ trait TraitChangeOrderOfMethods {
 
 
 // Change mode of self parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfRefToMut {
-    fn method(&self);
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(&    self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfRefToMut {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(&mut self);
 }
 
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfOwnToMut: Sized {
-    fn method(self) {}
+    // ----------------------------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------------------------
+    // -------------------------
+    fn method(    self) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfOwnToMut: Sized {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(mut self) {}
 }
 
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfOwnToRef {
-    fn method(self);
+    // ----------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------
+    // -------------------------
+    fn method( self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfOwnToRef {
     #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(&self);
 }
 
 
 
 // Add unsafe modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddUnsafeModifier {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method()       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddUnsafeModifier {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     unsafe fn method();
 }
 
 
 
 // Add extern modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddExternModifier {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method()           ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddExternModifier {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     extern "C" fn method();
 }
 
 
 
 // Change extern "C" to extern "stdcall"
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeExternCToRustIntrinsic {
-    extern "C" fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    extern "C"       fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeExternCToRustIntrinsic {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     extern "stdcall" fn method();
 }
 
 
 
 // Add type parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTypeParameterToMethod {
-    fn method();
+    // -------------------------------------------------------------------------------
+    // -------------------------
+    // -------------------------------------------------------------------------------
+    // -------------------------
+    fn method   ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTypeParameterToMethod {
     #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T>();
 }
 
 
 
 // Add lifetime parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeParameterToMethod {
-    fn method();
+    // ----------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------
+    // -------------------------
+    fn method    ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeParameterToMethod {
     #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a>();
 }
 
@@ -369,137 +517,220 @@ trait ReferencedTrait0 { }
 trait ReferencedTrait1 { }
 
 // Add trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToMethodTypeParameter {
-    fn method<T>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T                  >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: ReferencedTrait0>();
 }
 
 
 
 // Add builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
-    fn method<T>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T       >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: Sized>();
 }
 
 
 
 // Add lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
-    fn method<'a, 'b>(a: &'a u32, b: &'b u32);
-}
-
-#[cfg(not(cfail1))]
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    fn method<'a, 'b    >(a: &'a u32, b: &'b u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
 
 
 // Add second trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
-    fn method<T: ReferencedTrait0>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T: ReferencedTrait0                   >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
 
 
 // Add second builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
-    fn method<T: Sized>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T: Sized       >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: Sized + Sync>();
 }
 
 
 
 // Add second lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
-    fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32);
-}
-
-#[cfg(not(cfail1))]
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    fn method<'a, 'b, 'c: 'a     >(a: &'a u32, b: &'b u32, c: &'c u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
 
 
 // Add associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddAssociatedType {
-
-    #[rustc_clean(except="hir_owner", cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
+    //--------------------------
+    //--------------------------
+    // -------------
+
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddAssociatedType {
+    #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated;
 
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Add trait bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToAssociatedType {
-    type Associated;
+    // ---------------------------------------------
+    // -------------------------
+    // ---------------------------------------------
+    // -------------------------
+    type Associated                  ;
 
     fn method();
 }
@@ -507,12 +738,16 @@ trait TraitAddTraitBoundToAssociatedType {
 
 // Apparently the type bound contributes to the predicates of the trait, but
 // does not change the associated item itself.
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToAssociatedType {
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated: ReferencedTrait0;
 
     fn method();
@@ -521,19 +756,27 @@ trait TraitAddTraitBoundToAssociatedType {
 
 
 // Add lifetime bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
-    type Associated;
+    // ---------------------------------------------
+    // -------------------------
+    // ---------------------------------------------
+    // -------------------------
+    type Associated    ;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated: 'a;
 
     fn method();
@@ -542,19 +785,23 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 
 
 // Add default to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddDefaultToAssociatedType {
     type Associated;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddDefaultToAssociatedType {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated = ReferenceType0;
 
     fn method();
@@ -563,14 +810,16 @@ trait TraitAddDefaultToAssociatedType {
 
 
 // Add associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddAssociatedConstant {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
@@ -580,269 +829,331 @@ trait TraitAddAssociatedConstant {
 
 
 // Add initializer to associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddInitializerToAssociatedConstant {
     const Value: u32;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddInitializerToAssociatedConstant {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     const Value: u32 = 1;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Change type of associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeTypeOfAssociatedConstant {
+    // -----------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------
+    // -------------------------
     const Value: u32;
 
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_clean(except="hir_owner,type_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,type_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     const Value: f64;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Add super trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSuperTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSuperTrait : ReferencedTrait0 { }
 
 
 
 // Add builtin bound (Send or Copy)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltiBound { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltiBound : Send { }
 
 
 
 // Add 'static lifetime bound to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticLifetimeBound { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticLifetimeBound : 'static { }
 
 
 
 // Add super trait as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 
 
 
 // Add builtin bound as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 
 
 
 // Add 'static bounds as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 
 
 
 // Add type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTypeParameterToTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTypeParameterToTrait<T> { }
 
 
 
 // Add lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeParameterToTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeParameterToTrait<'a> { }
 
 
 
 // Add trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 
 
 // Add lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 
 
 
 // Add lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 
 
 
 // Add builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 
 
 // Add second type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTypeParameterToTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTypeParameterToTrait<T, S> { }
 
 
 
 // Add second lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeParameterToTrait<'a> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 
 
 
 // Add second trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
 
 
 
 // Add second lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 
 
 
 // Add second lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
 
 
 
 // Add second builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
 
 
@@ -853,105 +1164,125 @@ struct ReferenceType1 {}
 
 
 // Add trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 
 
 // Add lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 
 
 
 // Add lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
 
 
 
 // Add builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 
 
 // Add second trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
     where T: ReferencedTrait0 + ReferencedTrait1 { }
 
 
 
 // Add second lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
 
 
 
 // Add second lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
 
 
 
 // Add second builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
 // Change return type of method indirectly by modifying a use statement
 mod change_return_type_of_method_indirectly_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferenceType0 as ReturnType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferenceType1 as ReturnType;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     trait TraitChangeReturnType {
         #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
         #[rustc_clean(cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+        #[rustc_clean(cfg="cfail6")]
         fn method() -> ReturnType;
     }
 }
@@ -960,9 +1291,9 @@ trait TraitChangeReturnType {
 
 // Change type of method parameter indirectly by modifying a use statement
 mod change_method_parameter_type_indirectly_by_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferenceType0 as ArgType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferenceType1 as ArgType;
 
     #[rustc_clean(cfg="cfail2")]
@@ -978,9 +1309,9 @@ trait TraitChangeArgType {
 
 // Change trait bound of method type parameter indirectly by modifying a use statement
 mod change_method_parameter_type_bound_indirectly_by_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(cfg="cfail2")]
@@ -997,16 +1328,20 @@ trait TraitChangeBoundOfMethodTypeParameter {
 // Change trait bound of method type parameter in where clause indirectly
 // by modifying a use statement
 mod change_method_parameter_type_bound_indirectly_by_use_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
         #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
         #[rustc_clean(cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+        #[rustc_clean(cfg="cfail6")]
         fn method<T>(a: T) where T: Bound;
     }
 }
@@ -1015,9 +1350,9 @@ trait TraitChangeBoundOfMethodTypeParameterWhere {
 
 // Change trait bound of trait type parameter indirectly by modifying a use statement
 mod change_method_type_parameter_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
@@ -1032,13 +1367,15 @@ trait TraitChangeTraitBound<T: Bound> {
 // Change trait bound of trait type parameter in where clause indirectly
 // by modifying a use statement
 mod change_method_type_parameter_bound_indirectly_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     trait TraitChangeTraitBoundWhere<T> where T: Bound {
         fn method(a: T);
     }
index 2d547f1748cb4a5ee9815e6a93cfd511117ac726..d623810115ee8c4aec7d303362fe67bad9da94cc 100644 (file)
@@ -6,9 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 // Change Method Name -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodNameTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodNameTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait ChangeMethodNameTrait {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name2();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodNameTrait for Foo {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name2() { }
 }
 
@@ -53,17 +64,27 @@ pub trait ChangeMethodBodyTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodBodyTrait for Foo {
-    fn method_name() { }
+    // ----------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------
+    // -------------------------
+    fn method_name() {
+        //
+    }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodBodyTrait for Foo {
     #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() {
         ()
     }
@@ -77,18 +98,28 @@ pub trait ChangeMethodBodyTraitInlined {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodBodyTraitInlined for Foo {
+    // ------------------------------------------------------------------------
+    // -------------------------
+    // ------------------------------------------------------------------------
+    // -------------------------
     #[inline]
-    fn method_name() { }
+    fn method_name() {
+        // -----
+    }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodBodyTraitInlined for Foo {
     #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     fn method_name() {
         panic!()
@@ -97,30 +128,37 @@ fn method_name() {
 
 // Change Method Selfness ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodSelfnessTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodSelfnessTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeMethodSelfnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodSelfnessTrait for Foo {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self) {
         ()
     }
@@ -128,130 +166,151 @@ fn method_name(&self) {
 
 // Change Method Selfness -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait RemoveMethodSelfnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl RemoveMethodSelfnessTrait for Foo {
     fn method_name(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait RemoveMethodSelfnessTrait {
     fn method_name();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl RemoveMethodSelfnessTrait for Foo {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() {}
 }
 
 // Change Method Selfmutness -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodSelfmutnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodSelfmutnessTrait for Foo {
-    fn method_name(&self) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&    self) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeMethodSelfmutnessTrait {
     fn method_name(&mut self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodSelfmutnessTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&mut self) {}
 }
 
 // Change item kind -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeItemKindTrait {
     fn name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeItemKindTrait for Foo {
     fn name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeItemKindTrait {
     type name;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeItemKindTrait for Foo {
     type name = ();
 }
 
 // Remove item -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait RemoveItemTrait {
     type TypeName;
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait RemoveItemTrait {
     type TypeName;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
 }
 
 // Add item -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait AddItemTrait {
     type TypeName;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddItemTrait for Foo {
     type TypeName = ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait AddItemTrait {
     type TypeName;
     fn method_name();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
@@ -259,28 +318,34 @@ fn method_name() { }
 
 // Change has-value -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeHasValueTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait ChangeHasValueTrait {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
@@ -291,69 +356,91 @@ pub trait AddDefaultTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddDefaultTrait for Foo {
-    fn method_name() { }
+    // -------------------------------------------------------------------------------------------
+    // -------------------------
+            fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddDefaultTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     default fn method_name() { }
 }
 
 // Add arguments
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait AddArgumentTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddArgumentTrait for Foo {
-    fn method_name(&self) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&self         ) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait AddArgumentTrait {
     fn method_name(&self, x: u32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddArgumentTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self, _x: u32) { }
 }
 
 // Change argument type
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeArgumentTypeTrait {
     fn method_name(&self, x: u32);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeArgumentTypeTrait for Foo {
-    fn method_name(&self, _x: u32) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&self, _x: u32 ) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeArgumentTypeTrait {
     fn method_name(&self, x: char);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeArgumentTypeTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self, _x: char) { }
 }
 
@@ -366,21 +453,28 @@ trait AddTypeParameterToImpl<T> {
     fn id(t: T) -> T;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddTypeParameterToImpl<u32> for Bar<u32> {
     fn id(t: u32) -> u32 { t }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-impl<T> AddTypeParameterToImpl<T> for Bar<T> {
+#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<TTT> AddTypeParameterToImpl<TTT> for Bar<TTT> {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
-    fn id(t: T) -> T { t }
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
+    fn id(t: TTT) -> TTT { t }
 }
 
 
@@ -390,17 +484,21 @@ trait ChangeSelfTypeOfImpl {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeSelfTypeOfImpl for u32 {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeSelfTypeOfImpl for u64 {
     #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -411,17 +509,21 @@ trait AddLifetimeBoundToImplParameter {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> AddLifetimeBoundToImplParameter for T {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -432,17 +534,21 @@ trait AddTraitBoundToImplParameter {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> AddTraitBoundToImplParameter for T {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: Clone> AddTraitBoundToImplParameter for T {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -453,17 +559,26 @@ trait AddNoMangleToMethod {
     fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddNoMangleToMethod for Foo {
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // ---------
     fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddNoMangleToMethod for Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[no_mangle]
     fn add_no_mangle_to_method(&self) { }
 }
@@ -474,17 +589,26 @@ trait MakeMethodInline {
     fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl MakeMethodInline for Foo {
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // ------
     fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl MakeMethodInline for Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     fn make_method_inline(&self) -> u8 { 0 }
 }
index d874be060c26a080c8d74fa0bb943450ac31cce0..70c199bc3be7de8f992a88ef5c6bfbf902f8a1f3 100644 (file)
@@ -12,7 +12,7 @@
 
 // build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
index 687580ec8afb24b10b3ae5ba5e2ce0c95ca674f6..8d8345e10f5553f4b0efb5f0b9435f48e780c2b2 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
 
 // Change constant operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn const_negation() -> i32 {
     -10
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn const_negation() -> i32 {
-    -1
+     -1
 }
 
 
 
 // Change constant operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn const_bitwise_not() -> i32 {
     !100
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn const_bitwise_not() -> i32 {
-    !99
+     !99
 }
 
 
 
 // Change variable operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
 }
@@ -60,14 +72,16 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 
 
 // Change variable operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
 }
@@ -75,14 +89,16 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 
 
 // Change variable operand of deref --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
 }
@@ -90,14 +106,16 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 
 
 // Change first constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn first_const_add() -> i32 {
     1 + 3
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn first_const_add() -> i32 {
     2 + 3
 }
@@ -105,14 +123,16 @@ pub fn first_const_add() -> i32 {
 
 
 // Change second constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn second_const_add() -> i32 {
     1 + 2
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn second_const_add() -> i32 {
     1 + 3
 }
@@ -120,14 +140,16 @@ pub fn second_const_add() -> i32 {
 
 
 // Change first variable operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     a + 2
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
 }
@@ -135,14 +157,16 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 
 
 // Change second variable operand of addition ----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
 }
@@ -150,14 +174,16 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 
 
 // Change operator from + to - -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
 }
@@ -165,14 +191,16 @@ pub fn plus_to_minus(a: i32) -> i32 {
 
 
 // Change operator from + to * -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
 }
@@ -180,14 +208,16 @@ pub fn plus_to_mult(a: i32) -> i32 {
 
 
 // Change operator from + to / -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_div(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
 }
@@ -195,14 +225,16 @@ pub fn plus_to_div(a: i32) -> i32 {
 
 
 // Change operator from + to % -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
 }
@@ -210,14 +242,16 @@ pub fn plus_to_mod(a: i32) -> i32 {
 
 
 // Change operator from && to || -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a && b
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
 }
@@ -225,14 +259,16 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 
 
 // Change operator from & to | -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 & a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
 }
@@ -240,14 +276,16 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 
 
 // Change operator from & to ^ -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 & a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
 }
@@ -255,14 +293,16 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 
 
 // Change operator from & to << ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
-    a & 1
+    a  & 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
 }
@@ -270,14 +310,16 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 
 
 // Change operator from & to >> ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
-    a & 1
+    a  & 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
 }
@@ -285,14 +327,16 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 
 
 // Change operator from == to != -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_uneq(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
 }
@@ -300,44 +344,50 @@ pub fn eq_to_uneq(a: i32) -> bool {
 
 
 // Change operator from == to < ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_lt(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_lt(a: i32) -> bool {
-    a < 1
+    a  < 1
 }
 
 
 
 // Change operator from == to > ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_gt(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_gt(a: i32) -> bool {
-    a > 1
+    a  > 1
 }
 
 
 
 // Change operator from == to <= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_le(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
 }
@@ -345,14 +395,16 @@ pub fn eq_to_le(a: i32) -> bool {
 
 
 // Change operator from == to >= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_ge(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
 }
@@ -360,16 +412,18 @@ pub fn eq_to_ge(a: i32) -> bool {
 
 
 // Change type in cast expression ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as i32;
     let c = b as u64;
     c
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
     let c = b as u64;
@@ -379,14 +433,16 @@ pub fn type_cast(a: u8) -> u64 {
 
 
 // Change value in cast expression ---------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn value_cast(a: u32) -> i32 {
     1 as i32
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
 }
@@ -394,7 +450,7 @@ pub fn value_cast(a: u32) -> i32 {
 
 
 // Change place in assignment --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn place() -> i32 {
     let mut x = 10;
     let mut y = 11;
@@ -402,9 +458,11 @@ pub fn place() -> i32 {
     x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn place() -> i32 {
     let mut x = 10;
     let mut y = 11;
@@ -415,16 +473,18 @@ pub fn place() -> i32 {
 
 
 // Change r-value in assignment ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn rvalue() -> i32 {
     let mut x = 10;
     x = 9;
     x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
     x = 8;
@@ -434,14 +494,16 @@ pub fn rvalue() -> i32 {
 
 
 // Change index into slice -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[i]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
 }
index d385974893ca3e2f625e0b94c738983fd38df119..64a6517836cd80f708247c23aa893f76ac0b6eba 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -38,7 +46,7 @@ pub fn change_loop_body() {
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -47,9 +55,11 @@ pub fn change_loop_condition() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(1u32) = None {
@@ -61,17 +71,20 @@ pub fn change_loop_condition() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -83,18 +96,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    while let Some(0u32) = None {
+            while let Some(0u32) = None {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -106,18 +121,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -140,9 +157,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -154,18 +173,20 @@ pub fn change_break_label() {
 }
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -177,7 +198,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -188,9 +209,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -204,7 +227,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -213,13 +236,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
-        break;
+        break   ;
     }
 }
index 299622e45c67b179ecdeba760a6d0032663a3205..b8796d3446be72826328aff7ee9a64c8e3ca87ed 100644 (file)
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     while true {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     while true {
@@ -38,18 +46,20 @@ pub fn change_loop_body() {
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_condition() {
     let mut _x = 0;
-    while true {
+    while true  {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while false {
@@ -61,17 +71,20 @@ pub fn change_loop_condition() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     while true {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     while true {
@@ -83,18 +96,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    while true {
+            while true {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: while true {
@@ -106,18 +121,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
@@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
@@ -140,9 +157,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
@@ -156,18 +175,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
@@ -179,7 +200,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
@@ -190,9 +211,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
@@ -206,7 +229,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
@@ -215,13 +238,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
         _x = 1;
-        break;
+        break   ;
     }
 }
index 8506636e22b7be65c7e67063d820e5411b7c6181..639454cc975300dad6299d4a6cf761ad4450e5c7 100644 (file)
@@ -1,16 +1,21 @@
 // This test makes sure that just changing a definition's location in the
 // source file also changes its incr. comp. hash, if debuginfo is enabled.
 
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
 
 // ignore-asmjs wasm2js does not support source maps yet
 // compile-flags: -g -Z query-dep-graph
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 #![feature(rustc_attrs)]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")]
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
 pub fn main() {}
 
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
 pub fn main() {}
index a29b61ab153dcb6b4039de0eeb6e7e6a0195d251..e9e35791aa15800988b44f2cd21249ee7b7fce63 100644 (file)
@@ -1,19 +1,29 @@
 // This test makes sure that just changing a definition's location in the
 // source file also changes its incr. comp. hash, if debuginfo is enabled.
 
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 // compile-flags: -C overflow-checks=on -Z query-dep-graph
 
 #![feature(rustc_attrs)]
+#![feature(bench_black_box)]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
 pub fn main() {
-    let _ = 0u8 + 1;
+    if std::hint::black_box(false) {
+        panic!()
+    }
 }
 
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
 pub fn main() {
-    let _ = 0u8 + 1;
+    if std::hint::black_box(false) {
+        panic!()
+    }
 }
index 866f51d759ec4d5338b1d66cff40f479ca55f51b..cae7b4aab7565ed60455eec442a1a4de705760e2 100644 (file)
@@ -1,5 +1,7 @@
-// revisions: cfail1 cfail2
+// revisions: cfail1 cfail2 cfail3 cfail4
 // compile-flags: -Z query-dep-graph
+// [cfail3]compile-flags: -Zincremental-relative-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
 // build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
 // Therefore, the compiler deduces (correctly) that typeck is not
 // needed even for callers of `x`.
 
-
 pub mod x {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1, cfail3))]
     pub fn x() {
         println!("{}", "1");
     }
 
-    #[cfg(cfail2)]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg="cfail2")]
+    #[cfg(any(cfail2, cfail4))]
+    #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")]
+    #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")]
     pub fn x() {
         println!("{}", "2");
     }
@@ -27,7 +29,8 @@ pub fn x() {
 pub mod y {
     use x;
 
-    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg = "cfail2")]
+    #[rustc_clean(cfg = "cfail4")]
     pub fn y() {
         x::x();
     }
@@ -36,7 +39,8 @@ pub fn y() {
 pub mod z {
     use y;
 
-    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg = "cfail2")]
+    #[rustc_clean(cfg = "cfail4")]
     pub fn z() {
         y::y();
     }
index 0fd5abee11840996a234b0cd64f732d4f4a17878..31f329a7f726b2083d9b80837fc98a57158038dd 100644 (file)
@@ -3,36 +3,61 @@
 // ends up with any spans in its LLVM bitecode, so LLVM is able to skip
 // re-building any modules which import 'inlined_fn'
 
-// revisions: cfail1 cfail2 cfail3
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 // compile-flags: -Z query-dep-graph -O
 // build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
-#![crate_type="rlib"]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
-                            cfg="cfail2",
-                            kind="no")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
-                            cfg="cfail3",
-                            kind="post-lto")]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
-                            cfg="cfail2",
-                            kind="post-lto")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
-                            cfg="cfail3",
-                            kind="post-lto")]
+#![crate_type = "rlib"]
+#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail3",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail5",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail6",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail2",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail3",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail5",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail6",
+    kind = "post-lto"
+)]
 
 mod foo {
 
     // Trivial functions like this one are imported very reliably by ThinLTO.
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1, cfail4))]
     pub fn inlined_fn() -> u32 {
         1234
     }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1, cfail4)))]
     pub fn inlined_fn() -> u32 {
         1234
     }
index eeedbb215c0dd682b320782c75258b4c1c5ec71c..ca0eb7e845aade9bdbe7293051590e84b10fd159 100644 (file)
@@ -2,10 +2,12 @@ digraph Cov_0_3 {
     graph [fontname="Courier, monospace"];
     node [fontname="Courier, monospace"];
     edge [fontname="Courier, monospace"];
-    bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb0 - bcb1) at 13:10-13:10<br/>    13:10-13:10: @4[0]: Coverage::Expression(4294967295) = 1 - 2 for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb4: Goto</td></tr></table>>];
-    bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Counter(bcb1) at 12:13-12:18<br/>    12:13-12:18: @3[0]: Coverage::Expression(4294967294) = 2 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb1 + 0) at 15:2-15:2<br/>    15:2-15:2: @3.Return: return</td></tr><tr><td align="left" balign="left">bb3: Return</td></tr></table>>];
-    bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-11:17<br/>    11:12-11:17: @1.Call: _2 = bar() -&gt; [return: bb2, unwind: bb5]</td></tr><tr><td align="left" balign="left">bb0: FalseUnwind<br/>bb1: Call</td></tr><tr><td align="left" balign="left">bb2: SwitchInt</td></tr></table>>];
-    bcb2__Cov_0_3 -> bcb0__Cov_0_3 [label=<>];
-    bcb0__Cov_0_3 -> bcb2__Cov_0_3 [label=<false>];
-    bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<otherwise>];
+    bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br/>    13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>];
+    bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18<br/>    12:13-12:18: @4[0]: Coverage::Expression(4294967293) = 4294967294 + 0 for $DIR/coverage_graphviz.rs:15:1 - 15:2<br/>Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2<br/>    15:2-15:2: @4.Return: return</td></tr><tr><td align="left" balign="left">bb4: Return</td></tr></table>>];
+    bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br/>    11:12-11:17: @2.Call: _2 = bar() -&gt; [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
+    bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br/>    </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
+    bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
+    bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
+    bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
+    bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
 }
index e2fad5b60ebfaf49ff0cda071d872b44783ae58f..f810beeeee30c415eac063b2e7d49a94c7d03c27 100644 (file)
@@ -47,7 +47,7 @@
 +         _4 = &_2;                        // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
 +         StorageLive(_9);                 // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
 +         _9 = const ();                   // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
-+         goto -> bb1;                     // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22
++         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:22:5: 22:22
       }
   
       bb1: {
index 3539fc8b4876c0a8e021c1080103b23c6435356c..34ba7dfdcc5bb8cea0a6d5709ee24c23a432a80d 100644 (file)
@@ -8,38 +8,43 @@
       let mut _3: !;                       // in scope 0 at /the/src/instrument_coverage.rs:12:18: 14:10
   
       bb0: {
-+         Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
-          falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
++         Coverage::Counter(1) for /the/src/instrument_coverage.rs:10:1 - 10:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+          goto -> bb1;                     // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
       }
   
       bb1: {
++         Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:11:5 - 12:17; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+          falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+      }
+  
+      bb2: {
           StorageLive(_2);                 // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
-          _2 = bar() -> [return: bb2, unwind: bb5]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+          _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
                                            // mir::Constant
                                            // + span: /the/src/instrument_coverage.rs:12:12: 12:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
       }
   
-      bb2: {
-          switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
+      bb3: {
+          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:12:12: 12:17
       }
   
-      bb3: {
-+         Coverage::Expression(4294967294) = 2 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
-+         Coverage::Counter(2) for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
+      bb4: {
++         Coverage::Expression(4294967293) = 4294967294 + 0 for /the/src/instrument_coverage.rs:16:1 - 16:2; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
++         Coverage::Expression(4294967294) = 4294967295 - 2 for /the/src/instrument_coverage.rs:13:13 - 13:18; // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
           _0 = const ();                   // scope 0 at /the/src/instrument_coverage.rs:13:13: 13:18
           StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
           return;                          // scope 0 at /the/src/instrument_coverage.rs:16:2: 16:2
       }
   
-      bb4: {
-+         Coverage::Expression(4294967295) = 1 - 2 for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+      bb5: {
++         Coverage::Counter(2) for /the/src/instrument_coverage.rs:14:10 - 14:11; // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
           _1 = const ();                   // scope 0 at /the/src/instrument_coverage.rs:14:10: 14:10
           StorageDead(_2);                 // scope 0 at /the/src/instrument_coverage.rs:14:9: 14:10
-          goto -> bb0;                     // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
+          goto -> bb1;                     // scope 0 at /the/src/instrument_coverage.rs:11:5: 15:6
       }
   
-      bb5 (cleanup): {
+      bb6 (cleanup): {
           resume;                          // scope 0 at /the/src/instrument_coverage.rs:10:1: 16:2
       }
   }
diff --git a/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
new file mode 100644 (file)
index 0000000..3f5f71f
--- /dev/null
@@ -0,0 +1,24 @@
+- // MIR for `align_of` before LowerIntrinsics
++ // MIR for `align_of` after LowerIntrinsics
+  
+  fn align_of() -> usize {
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:18:25: 18:30
+  
+      bb0: {
+-         _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:19:5: 19:40
+-                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(Scalar(<ZST>)) }
++         _0 = AlignOf(T);                 // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+      }
+  
+      bb1: {
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+      }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+      }
+  }
+  
index f427375e5a624ddbf9d5afd66e973362d980a02e..d9b441a470c1ee921d9a1b1d51b0bf9699d3e853 100644 (file)
 + // MIR for `discriminant` after LowerIntrinsics
   
   fn discriminant(_1: T) -> () {
-      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:68:24: 68:25
-      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:68:30: 68:30
-      let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-      let mut _3: &T;                      // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-      let _4: &T;                          // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-      let _5: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-      let mut _6: &i32;                    // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-      let _7: &i32;                        // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-      let _8: i32;                         // in scope 0 at $DIR/lower_intrinsics.rs:70:43: 70:44
-      let _9: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-      let mut _10: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let _11: &();                        // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let _12: ();                         // in scope 0 at $DIR/lower_intrinsics.rs:71:43: 71:45
-      let _13: isize;                      // in scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-      let mut _14: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let _15: &E;                         // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let _16: E;                          // in scope 0 at $DIR/lower_intrinsics.rs:72:43: 72:47
-      let mut _17: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let mut _18: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let mut _19: &i32;                   // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:73:24: 73:25
+      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:73:30: 73:30
+      let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+      let mut _3: &T;                      // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+      let _4: &T;                          // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+      let _5: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+      let mut _6: &i32;                    // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+      let _7: &i32;                        // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+      let _8: i32;                         // in scope 0 at $DIR/lower_intrinsics.rs:75:43: 75:44
+      let _9: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+      let mut _10: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let _11: &();                        // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let _12: ();                         // in scope 0 at $DIR/lower_intrinsics.rs:76:43: 76:45
+      let _13: isize;                      // in scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+      let mut _14: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let _15: &E;                         // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let _16: E;                          // in scope 0 at $DIR/lower_intrinsics.rs:77:43: 77:47
+      let mut _17: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let mut _18: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let mut _19: &i32;                   // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-          StorageLive(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
--         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+          StorageLive(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+-         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:69:5: 69:41
+-                                          // + span: $DIR/lower_intrinsics.rs:74:5: 74:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<T>}, val: Value(Scalar(<ZST>)) }
-+         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-+         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
++         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
       }
   
       bb1: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:69:44: 69:45
-          StorageDead(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
-          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
-          StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-          StorageLive(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-          StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-          _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+          StorageDead(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:74:44: 74:45
+          StorageDead(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+          StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+          StorageLive(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
                                            // ty::Const
                                            // + ty: &i32
                                            // + 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_: 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
+                                           // + span: $DIR/lower_intrinsics.rs:75:42: 75:44
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
+          _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+-         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:70:5: 70:41
+-                                          // + span: $DIR/lower_intrinsics.rs:75:5: 75:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<i32>}, val: Value(Scalar(<ZST>)) }
-+         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-+         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
++         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
++         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
       }
   
       bb2: {
-          StorageDead(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:70:44: 70:45
-          StorageDead(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
-          StorageDead(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
-          StorageLive(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-          StorageLive(_10);                // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-          StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-          _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
+          StorageDead(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:75:44: 75:45
+          StorageDead(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+          StorageDead(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+          StorageLive(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+          StorageLive(_10);                // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
                                            // ty::Const
                                            // + ty: &()
                                            // + 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_: 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
+                                           // + span: $DIR/lower_intrinsics.rs:76:42: 76:45
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
+          _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+-         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:71:5: 71:41
+-                                          // + span: $DIR/lower_intrinsics.rs:76:5: 76:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<()>}, val: Value(Scalar(<ZST>)) }
-+         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-+         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
++         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
++         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
       }
   
       bb3: {
-          StorageDead(_10);                // scope 0 at $DIR/lower_intrinsics.rs:71:45: 71:46
-          StorageDead(_11);                // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
-          StorageDead(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
-          StorageLive(_13);                // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-          StorageLive(_14);                // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-          StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-          _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
+          StorageDead(_10);                // scope 0 at $DIR/lower_intrinsics.rs:76:45: 76:46
+          StorageDead(_11);                // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+          StorageDead(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+          StorageLive(_13);                // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+          StorageLive(_14);                // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
                                            // ty::Const
                                            // + ty: &E
                                            // + 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_: 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
+                                           // + span: $DIR/lower_intrinsics.rs:77:42: 77:47
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
+          _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+-         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:72:5: 72:41
+-                                          // + span: $DIR/lower_intrinsics.rs:77:5: 77:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<E>}, val: Value(Scalar(<ZST>)) }
-+         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-+         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
++         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
++         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
       }
   
       bb4: {
-          StorageDead(_14);                // scope 0 at $DIR/lower_intrinsics.rs:72:47: 72:48
-          StorageDead(_15);                // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
-          StorageDead(_13);                // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
-          _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:68:30: 73:2
-          drop(_1) -> bb5;                 // scope 0 at $DIR/lower_intrinsics.rs:73:1: 73:2
+          StorageDead(_14);                // scope 0 at $DIR/lower_intrinsics.rs:77:47: 77:48
+          StorageDead(_15);                // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+          StorageDead(_13);                // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+          _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:73:30: 78:2
+          drop(_1) -> bb5;                 // scope 0 at $DIR/lower_intrinsics.rs:78:1: 78:2
       }
   
       bb5: {
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:73:2: 73:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:78:2: 78:2
       }
   
       bb6 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:68:1: 73:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:73:1: 78:2
       }
   }
   
index 380f6ce9ba73ed6ddbf25e400260200ae489e441..2f3fd9ad28565568944a25129191fe1b8b498438 100644 (file)
@@ -1,32 +1,32 @@
 // MIR for `f_u64` before PreCodegen
 
 fn f_u64() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
-    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:39:16: 39:16
+    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
                                          // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:35:5: 35:21
+                                         // + span: $DIR/lower_intrinsics.rs:40:5: 40:21
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        return;                          // scope 0 at $DIR/lower_intrinsics.rs:41:2: 41:2
     }
 }
index 2b9ffaaf971087b52fdb34606170765885862268..690405c4748eee5c95874af4eab805865b1e4d74 100644 (file)
@@ -1,27 +1,27 @@
 // MIR for `f_unit` before PreCodegen
 
 fn f_unit() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:28:17: 28:17
-    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
-    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:33:17: 33:17
+    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
                                          // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:29:5: 29:19
+                                         // + span: $DIR/lower_intrinsics.rs:34:5: 34:19
                                          // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:29:18: 29:19
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:30:2: 30:2
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:34:18: 34:19
+        return;                          // scope 0 at $DIR/lower_intrinsics.rs:35:2: 35:2
     }
 }
index 096bba64c0bb882522373957cc04aa07f3df9440..7e1e066366c1151b651267536593065507143ed1 100644 (file)
@@ -2,32 +2,32 @@
 + // MIR for `forget` after LowerIntrinsics
   
   fn forget(_1: T) -> () {
-      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:18:18: 18:19
-      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:18:24: 18:24
-      let mut _2: T;                       // in scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
+      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:23:18: 23:19
+      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:23:24: 23:24
+      let mut _2: T;                       // in scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
-          _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
--         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+          _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+-         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:19:5: 19:29
+-                                          // + span: $DIR/lower_intrinsics.rs:24:5: 24:29
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(Scalar(<ZST>)) }
-+         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
-+         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
++         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
       }
   
       bb1: {
-          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:19:31: 19:32
-          goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:20:1: 20:2
+          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:31: 24:32
+          goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:25:1: 25:2
       }
   
       bb2: {
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:25:2: 25:2
       }
   
       bb3 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
       }
   }
   
index 218b1c964334525ac622f6d12fe1ddee158ac905..276227d8c018a0c97387c6c477a8a5bc12329f25 100644 (file)
@@ -2,34 +2,34 @@
 + // MIR for `non_const` after LowerIntrinsics
   
   fn non_const() -> usize {
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:55:26: 55:31
-      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
-      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:58:5: 58:14
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:60:26: 60:31
+      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:63:5: 63:14
       scope 1 {
-          debug size_of_t => _1;           // in scope 1 at $DIR/lower_intrinsics.rs:57:9: 57:18
+          debug size_of_t => _1;           // in scope 1 at $DIR/lower_intrinsics.rs:62:9: 62:18
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
-          _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:57:21: 57:51
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+          _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:62:21: 62:51
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:57:21: 57:51
+                                           // + span: $DIR/lower_intrinsics.rs:62:21: 62:51
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
-          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
--         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+-         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
       }
   
       bb1: {
-          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:15: 58:16
-          StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:59:1: 59:2
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:59:2: 59:2
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:63:15: 63:16
+          StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:64:1: 64:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:64:2: 64:2
       }
   
       bb2 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:55:1: 59:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:60:1: 64:2
       }
   }
   
index d9891465dabb743fc4afd282f76549e7b2205f4c..8a8880dad02e5032aab3b7bbad2422ee44f48c65 100644 (file)
@@ -14,6 +14,11 @@ pub fn size_of<T>() -> usize {
     core::intrinsics::size_of::<T>()
 }
 
+// EMIT_MIR lower_intrinsics.align_of.LowerIntrinsics.diff
+pub fn align_of<T>() -> usize {
+    core::intrinsics::min_align_of::<T>()
+}
+
 // EMIT_MIR lower_intrinsics.forget.LowerIntrinsics.diff
 pub fn forget<T>(t: T) {
     core::intrinsics::forget(t)
index a04b79d47d4ce59fe62deaeef8676b98c9b3cae4..50711f574f1c1e597ad88f97b6b033ee763fedcf 100644 (file)
@@ -2,25 +2,25 @@
 + // MIR for `unreachable` after LowerIntrinsics
   
   fn unreachable() -> ! {
-      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:23:25: 23:26
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:23:27: 25:2
-      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
+      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:28:25: 28:26
+      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:28:27: 30:2
+      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
+      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:47
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
--         std::intrinsics::unreachable();  // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:29:5: 29:47
+          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
+-         std::intrinsics::unreachable();  // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:24:14: 24:43
+-                                          // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar(<ZST>)) }
-+         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
++         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
       }
   
       bb1 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:28:1: 30:2
       }
   }
   
index 6d6c2721973f80374c489324889c8d7f2f9fb097..02f6e55a9a8b6b56e098eaa3c01eaf22ebfbee56 100644 (file)
@@ -80,7 +80,7 @@
 -         StorageDead(_7);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
 -         StorageDead(_6);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_4);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
--         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
+-         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_1);                 // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2
           return;                          // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
       }
index eac9328500d29eb82525575bfd037f87a10a2fb9..1c5a890023648478c3c714ba208529b1d27a3e70 100644 (file)
@@ -8,40 +8,44 @@
       let mut _3: !;                       // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
   
       bb0: {
--         goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+          goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+      }
+  
+      bb1: {
+-         goto -> bb2;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
 -     }
 - 
--     bb1: {
+-     bb2: {
           StorageLive(_2);                 // 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
-+         _2 = bar() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
+-         _2 = bar() -> [return: bb3, unwind: bb6]; // 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
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
       }
   
--     bb2: {
--         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:12: 9:17
-      }
-  
 -     bb3: {
+-         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:12: 9:17
+      }
+  
+-     bb4: {
++     bb3: {
           _0 = const ();                   // 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
       }
   
--     bb4: {
-+     bb3: {
+-     bb5: {
++     bb4: {
           _1 = const ();                   // scope 0 at $DIR/simplify_cfg.rs:11:10: 11:10
           StorageDead(_2);                 // scope 0 at $DIR/simplify_cfg.rs:11:9: 11:10
-          goto -> bb0;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+          goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
       }
   
--     bb5 (cleanup): {
-+     bb4 (cleanup): {
+-     bb6 (cleanup): {
++     bb5 (cleanup): {
           resume;                          // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
       }
   }
index f5ac2a41f5f5bf5d98be781f4c634aba5ae7f3a2..b079bd7b57c42c751a680808b6b9cc23976d0bd8 100644 (file)
@@ -8,38 +8,35 @@
       let mut _3: !;                       // in scope 0 at $DIR/simplify_cfg.rs:9:18: 11:10
   
       bb0: {
--         goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
-+         falseUnwind -> [real: bb1, cleanup: bb5]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
+          goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
       }
   
       bb1: {
 -         falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
--     }
-- 
--     bb2: {
++         falseUnwind -> [real: bb2, cleanup: bb6]; // 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: 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
++         _2 = bar() -> [return: bb3, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
                                            // mir::Constant
                                            // + span: $DIR/simplify_cfg.rs:9:12: 9:15
                                            // + literal: Const { ty: fn() -> bool {bar}, val: Value(Scalar(<ZST>)) }
       }
   
--     bb3: {
--         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:12: 9:17
+      bb3: {
+          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
       }
   
--     bb4: {
-+     bb3: {
+      bb4: {
           _0 = const ();                   // 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: {
+      bb5: {
 -         goto -> bb8;                     // scope 0 at $DIR/simplify_cfg.rs:9:12: 9:17
 -     }
 - 
 -     }
 - 
 -     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
+          goto -> bb1;                     // scope 0 at $DIR/simplify_cfg.rs:8:5: 12:6
       }
   
 -     bb10: {
@@ -69,7 +64,7 @@
 -     }
 - 
 -     bb11 (cleanup): {
-+     bb5 (cleanup): {
++     bb6 (cleanup): {
           resume;                          // scope 0 at $DIR/simplify_cfg.rs:7:1: 13:2
       }
   }
index 9db77d705ff99668492f892110e927a403185c26..ec2d161251b00fe22f0da2610f437ae23b146f74 100644 (file)
@@ -9,51 +9,55 @@ fn while_loop(_1: bool) -> () {
     let mut _5: bool;                    // in scope 0 at $DIR/while-storage.rs:11:21: 11:22
 
     bb0: {
+        goto -> bb1;                     // scope 0 at $DIR/while-storage.rs:10:5: 14:6
+    }
+
+    bb1: {
         StorageLive(_2);                 // scope 0 at $DIR/while-storage.rs:10:11: 10:22
         StorageLive(_3);                 // scope 0 at $DIR/while-storage.rs:10:20: 10:21
         _3 = _1;                         // scope 0 at $DIR/while-storage.rs:10:20: 10:21
-        _2 = get_bool(move _3) -> bb1;   // scope 0 at $DIR/while-storage.rs:10:11: 10:22
+        _2 = get_bool(move _3) -> bb2;   // scope 0 at $DIR/while-storage.rs:10:11: 10:22
                                          // mir::Constant
                                          // + span: $DIR/while-storage.rs:10:11: 10:19
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(Scalar(<ZST>)) }
     }
 
-    bb1: {
+    bb2: {
         StorageDead(_3);                 // scope 0 at $DIR/while-storage.rs:10:21: 10:22
-        switchInt(move _2) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
+        switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while-storage.rs:10:11: 10:22
     }
 
-    bb2: {
+    bb3: {
         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) -> bb3;   // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+        _4 = get_bool(move _5) -> bb4;   // 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: {
+    bb4: {
         StorageDead(_5);                 // scope 0 at $DIR/while-storage.rs:11:22: 11:23
-        switchInt(move _4) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
+        switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while-storage.rs:11:12: 11:23
     }
 
-    bb4: {
+    bb5: {
         StorageDead(_4);                 // scope 0 at $DIR/while-storage.rs:13:9: 13:10
-        goto -> bb7;                     // scope 0 at no-location
+        goto -> bb8;                     // scope 0 at no-location
     }
 
-    bb5: {
+    bb6: {
         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
+        goto -> bb1;                     // scope 0 at $DIR/while-storage.rs:10:5: 14:6
     }
 
-    bb6: {
-        goto -> bb7;                     // scope 0 at no-location
+    bb7: {
+        goto -> bb8;                     // scope 0 at no-location
     }
 
-    bb7: {
+    bb8: {
         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
     }
diff --git a/src/test/pretty/anonymous-types.rs b/src/test/pretty/anonymous-types.rs
deleted file mode 100644 (file)
index 5ff452e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Test for issue 85480
-// Pretty print anonymous struct and union types
-
-// pp-exact
-// pretty-compare-only
-
-struct Foo {
-    _: union {
-           _: struct {
-                  a: u8,
-                  b: u16,
-              },
-           c: u32,
-       },
-    d: u64,
-    e: f32,
-}
-
-type A =
- struct {
-     field: u8,
- };
-
-fn main() { }
index a17ec212cfd58250f3185c1d2302c00bf9eb7e84..adccc153568485f0fc62124c2f60e107d87ae3ea 100644 (file)
@@ -9,9 +9,19 @@ all:  \
        opt \
        link_paths \
        remap_paths \
-       different_source_dirs \
+       different_source_dirs_rlib \
+       remap_cwd_rlib \
+       remap_cwd_to_empty \
        extern_flags
 
+# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on
+# Windows.
+# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533
+# Issue: https://github.com/rust-lang/rust/issues/88982
+#
+#      different_source_dirs_bin \
+#      remap_cwd_bin \
+
 smoke:
        rm -rf $(TMPDIR) && mkdir $(TMPDIR)
        $(RUSTC) linker.rs -O
@@ -52,7 +62,19 @@ remap_paths:
        $(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c
        cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
 
-different_source_dirs:
+different_source_dirs_bin:
+       rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+       $(RUSTC) reproducible-build-aux.rs
+       mkdir $(TMPDIR)/test
+       cp reproducible-build.rs $(TMPDIR)/test
+       $(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b
+       cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo
+       (cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \
+               --remap-path-prefix=$(TMPDIR)/test=/b \
+               --crate-type bin)
+       cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1
+
+different_source_dirs_rlib:
        rm -rf $(TMPDIR) && mkdir $(TMPDIR)
        $(RUSTC) reproducible-build-aux.rs
        mkdir $(TMPDIR)/test
@@ -64,6 +86,45 @@ different_source_dirs:
                --crate-type rlib)
        cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
 
+remap_cwd_bin:
+       rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+       $(RUSTC) reproducible-build-aux.rs
+       mkdir $(TMPDIR)/test
+       cp reproducible-build.rs $(TMPDIR)/test
+       $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+         -Z remap-cwd-prefix=.
+       cp $(TMPDIR)/reproducible-build $(TMPDIR)/first
+       (cd $(TMPDIR)/test && \
+        $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+          -Z remap-cwd-prefix=.)
+       cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1
+
+remap_cwd_rlib:
+       rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+       $(RUSTC) reproducible-build-aux.rs
+       mkdir $(TMPDIR)/test
+       cp reproducible-build.rs $(TMPDIR)/test
+       $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+         -Z remap-cwd-prefix=.
+       cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+       (cd $(TMPDIR)/test && \
+        $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+          -Z remap-cwd-prefix=.)
+       cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
+remap_cwd_to_empty:
+       rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+       $(RUSTC) reproducible-build-aux.rs
+       mkdir $(TMPDIR)/test
+       cp reproducible-build.rs $(TMPDIR)/test
+       $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+         -Z remap-cwd-prefix=
+       cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+       (cd $(TMPDIR)/test && \
+        $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+          -Z remap-cwd-prefix=)
+       cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
 extern_flags:
        rm -rf $(TMPDIR) && mkdir $(TMPDIR)
        $(RUSTC) reproducible-build-aux.rs
index f479bdabb9c0c67313bfe2632114c5a9de4fd84e..cb77eb34fef08d77246fe41bdf4eec42d9be6b78 100644 (file)
@@ -17,6 +17,17 @@ def convert_to_string(s):
     return s
 
 
+def set_ld_lib_path():
+    var = os.environ.get("LD_LIB_PATH_ENVVAR")
+    rpath = os.environ.get("HOST_RPATH_DIR")
+    if var and rpath:
+        path = os.environ.get(var)
+        if path:
+            os.environ[var] = rpath + os.pathsep + path
+        else:
+            os.environ[var] = rpath
+
+
 def exec_command(command, to_input=None):
     child = None
     if to_input is None:
@@ -50,7 +61,9 @@ def get_all_libs(dir_path):
             if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES]
 
 
+set_ld_lib_path()
 sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '')
+assert sysroot, "Could not read the rustc sysroot!"
 libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET'])))
 
 ret = 0
index 00326e9bbc4ccfd5d8cae0ea5182ba5958cf1fc1..6fb92e196602e399c87a8746a3d7d38809cf66b2 100644 (file)
@@ -1,5 +1,6 @@
 goto: file://|DOC_PATH|/test_docs/index.html
 click: ".srclink"
+wait-for: "#sidebar-toggle"
 click: "#sidebar-toggle"
 wait-for: 500
 fail: true
index 9ab7cd0fa07b04c4dd2ad746e5380c9884af8e63..10f516d2dae06703003c3a1336ad0da560207867 100644 (file)
@@ -7,3 +7,11 @@ compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["sc
 assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
+
+// Checking it works on other doc blocks as well...
+
+// Logically, the ".docblock" and the "<p>" should have the same scroll width.
+compare-elements-property: ("#implementations + details .docblock", "#implementations + details .docblock > p", ["scrollWidth"])
+assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"})
+// However, since there is overflow in the <table>, its scroll width is bigger.
+assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml
new file mode 100644 (file)
index 0000000..3df899e
--- /dev/null
@@ -0,0 +1,23 @@
+// We check the background color on the jump to definition links in the source code page.
+goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+
+// Set the theme to dark.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to ayu.
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to light.
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL)
index cb63a9f60022702881b01a86ac23d0299b5226f0..d5835b78d2fcf17a5d9457c0c9de39a691cd80af 100644 (file)
@@ -67,6 +67,15 @@ pub mod long_table {
     ///
     /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
     pub struct Foo;
+
+    /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two |
+    /// | ----------- | ----------- | ----------- | ----------- |
+    /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two |
+    ///
+    /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
+    impl Foo {
+        pub fn foo(&self) {}
+    }
 }
 
 pub mod summary_table {
diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock
new file mode 100644 (file)
index 0000000..e4b4e52
--- /dev/null
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "link_to_definition"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml
new file mode 100644 (file)
index 0000000..cdd294d
--- /dev/null
@@ -0,0 +1,7 @@
+[package]
+name = "link_to_definition"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/link_to_definition/lib.rs b/src/test/rustdoc-gui/src/link_to_definition/lib.rs
new file mode 100644 (file)
index 0000000..de9ee66
--- /dev/null
@@ -0,0 +1,6 @@
+pub struct Bar {
+    pub a: String,
+    pub b: u32,
+}
+
+pub fn foo(_b: &Bar) {}
index 01e54065189c54e592c4a5281b1c246c896b20b2..1c92d019606b673f056ecd613478c877eb6d8afc 100644 (file)
@@ -2,8 +2,9 @@ const QUERY = 'str,u8';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std', 'name': 'str' },
-        { 'path': 'std', 'name': 'u8' },
-        { 'path': 'std::ffi', 'name': 'CStr' },
+        { 'path': 'std', 'name': 'str', 'href': '../std/primitive.str.html' },
+        { 'path': 'std', 'name': 'u8', 'href': '../std/primitive.u8.html'  },
+        { 'path': 'std', 'name': 'str', 'href': '../std/str/index.html' },
+        { 'path': 'std', 'name': 'u8', 'href': '../std/u8/index.html' },
     ],
 };
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs
new file mode 100644 (file)
index 0000000..e9c165b
--- /dev/null
@@ -0,0 +1,37 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+// The point of this test is to ensure that the number of "documented" items
+// is higher than in `enum-tuple.rs`.
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+    /// VarOne.
+    VarOne(
+        /// hello!
+        String,
+    ),
+    /// Var Two.
+    VarTwo(
+        /// Hello
+        String,
+        /// Bis repetita.
+        String,
+    ),
+}
+
+/// Struct.
+pub struct ThisStruct(
+    /// hello
+    u32,
+);
+
+/// Struct.
+pub struct ThisStruct2(
+    /// hello
+    u32,
+    /// Bis repetita.
+    u8,
+);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout
new file mode 100644 (file)
index 0000000..82c98f4
--- /dev/null
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...overage/enum-tuple-documented.rs |          9 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          9 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.rs b/src/test/rustdoc-ui/coverage/enum-tuple.rs
new file mode 100644 (file)
index 0000000..5fb2054
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+    /// No need to document the field if there is only one in a tuple variant!
+    VarOne(String),
+    /// But if there is more than one... still fine!
+    VarTwo(String, String),
+}
+
+/// Struct.
+pub struct ThisStruct(u32);
+
+/// Struct.
+pub struct ThisStruct2(u32, u8);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.stdout b/src/test/rustdoc-ui/coverage/enum-tuple.stdout
new file mode 100644 (file)
index 0000000..a3377d5
--- /dev/null
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...ustdoc-ui/coverage/enum-tuple.rs |          6 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          6 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
index 414d60c86d3083b80d9558f659823b01d7ec106a..64c012c1f66e3dfea1eea7a743511b78a08e0f5f 100644 (file)
@@ -1,7 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/enums.rs |          6 |      66.7% |          0 |       0.0% |
+| ...est/rustdoc-ui/coverage/enums.rs |          6 |      75.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
-| Total                               |          6 |      66.7% |          0 |       0.0% |
+| Total                               |          6 |      75.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/display-output.rs b/src/test/rustdoc-ui/display-output.rs
new file mode 100644 (file)
index 0000000..5e39002
--- /dev/null
@@ -0,0 +1,9 @@
+// check-pass
+// compile-flags:-Zunstable-options --display-doctest-warnings --test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let x = 12;
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout
new file mode 100644 (file)
index 0000000..00467b9
--- /dev/null
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/display-output.rs - foo (line 6) ... ok
+
+successes:
+
+---- $DIR/display-output.rs - foo (line 6) stdout ----
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:7:5
+   |
+LL | let x = 12;
+   |     ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+
+
+
+successes:
+    $DIR/display-output.rs - foo (line 6)
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
index 6785cb7abeaee3ea26bc305e606fba6b7a995a90..34e11c7c7b7cf6ca06f7dc47bafb2f7ffcbb5c28 100644 (file)
@@ -37,13 +37,3 @@ pub fn bar() {}
 /// Damn enum's variants: [Enum::A#whatever].
 //~^ ERROR `Enum::A#whatever` contains an anchor
 pub fn enum_link() {}
-
-/// Primitives?
-///
-/// [u32#hello]
-//~^ ERROR `u32#hello` contains an anchor
-pub fn x() {}
-
-/// [prim@usize#x]
-//~^ ERROR `prim@usize#x` contains an anchor
-pub mod usize {}
index d63e1ee60b3c5754db791ac38ed27345a59ee1bc..0d226b277535ce047702b5690a8e3645d099fb59 100644 (file)
@@ -1,19 +1,3 @@
-error: `prim@usize#x` contains an anchor, but links to builtin types are already anchored
-  --> $DIR/anchors.rs:47:6
-   |
-LL | /// [prim@usize#x]
-   |      ^^^^^^^^^^--
-   |                |
-   |                invalid anchor
-   |
-note: the lint level is defined here
-  --> $DIR/anchors.rs:1:9
-   |
-LL | #![deny(rustdoc::broken_intra_doc_links)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this restriction may be lifted in a future release
-   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
 error: `Foo::f#hola` contains an anchor, but links to fields are already anchored
   --> $DIR/anchors.rs:25:15
    |
@@ -21,6 +5,12 @@ LL | /// Or maybe [Foo::f#hola].
    |               ^^^^^^-----
    |                     |
    |                     invalid anchor
+   |
+note: the lint level is defined here
+  --> $DIR/anchors.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `hello#people#!` contains multiple anchors
   --> $DIR/anchors.rs:31:28
@@ -38,16 +28,5 @@ LL | /// Damn enum's variants: [Enum::A#whatever].
    |                                   |
    |                                   invalid anchor
 
-error: `u32#hello` contains an anchor, but links to builtin types are already anchored
-  --> $DIR/anchors.rs:43:6
-   |
-LL | /// [u32#hello]
-   |      ^^^------
-   |         |
-   |         invalid anchor
-   |
-   = note: this restriction may be lifted in a future release
-   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
index 5b1846a49d19fe0e7ef634f68e61a4cba58df46a..4c6249cc6d9e176d1f5c2bb5c072ee063e5e52bf 100644 (file)
@@ -14,7 +14,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:9:5
@@ -32,7 +32,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:21:5
@@ -47,7 +47,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:35:5
@@ -123,7 +123,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:92:9
@@ -148,7 +148,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: 12 warnings emitted
 
index 41e8847792694635d97ecdfe1a6b70ff75ffb870..fac6342cd24b9e86da8152b50c1e574e7d9b4973 100644 (file)
@@ -70,6 +70,22 @@ pub union Union {
     b: f32,
 }
 
+// no code example and it's fine!
+impl Clone for Struct {
+    fn clone(&self) -> Self {
+        Self { field: self.field }
+    }
+}
+
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+#[derive(Clone)]
+pub struct NiceStruct;
 
 #[doc(hidden)]
 pub mod foo {
index 83cc31b587c29674b9f96ab96a4c89979ce8b3cc..695fa58ef1d55e500eae3c71fabe2f545cfb15be 100644 (file)
@@ -1,6 +1,15 @@
+// no-prefer-dynamic
 // compile-flags: -Cmetadata=aux
-
+#![crate_type = "rlib"]
 #![doc(html_root_url = "http://example.com/")]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
 
 /// dox
 #[doc(primitive = "pointer")]
index a5b69740dd447c9e99944eafb0d4ad278f4e5de8..e8da852a57e631fd32a5938a7a2e4c939e3a36d7 100644 (file)
@@ -1,5 +1,8 @@
 // compile-flags: --crate-type lib --edition 2018
 
+#![feature(no_core)]
+#![no_core]
+
 #[doc(primitive = "usize")]
 /// This is the built-in type `usize`.
 mod usize {
diff --git a/src/test/rustdoc/check-source-code-urls-to-def-std.rs b/src/test/rustdoc/check-source-code-urls-to-def-std.rs
new file mode 100644 (file)
index 0000000..b129ceb
--- /dev/null
@@ -0,0 +1,17 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
+
+#![crate_name = "foo"]
+
+// @has 'src/foo/check-source-code-urls-to-def-std.rs.html'
+
+fn babar() {}
+
+// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str'
+// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar'
+pub fn foo(a: u32, b: &str, c: String) {
+    let x = 12;
+    let y: bool = true;
+    babar();
+}
index e3ae79ccdb17ad52effb5bdc8d04ec2da9a0daa8..0cb8e4230166ff0d2484afd7e8142479938bcce9 100644 (file)
@@ -27,6 +27,8 @@ fn hello(&self) {}
 fn babar() {}
 
 // @has - '//a/@href' '/struct.String.html'
+// @has - '//a/@href' '/primitive.u32.html'
+// @has - '//a/@href' '/primitive.str.html'
 // @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
 // @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
 pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
@@ -40,5 +42,9 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour
 
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait'
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait'
-pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V) {
+pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {
 }
+
+// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool'
+#[doc(primitive = "bool")]
+mod whatever {}
index 05376e4680ec4d5477ba8667835a3ce4baa1f213..120b6e9747f4aef1f8f1da144f5e6365f38b6dd0 100644 (file)
@@ -1,9 +1,13 @@
 // aux-build:primitive-doc.rs
 // compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
+// ignore-windows
 
-#![no_std]
+#![feature(no_core)]
+#![no_core]
 
 extern crate primitive_doc;
 
 // @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize'
+// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link'
+/// [link](usize)
 pub fn foo() -> usize { 0 }
index 8ec1a7b4f9056381784dda314f1537252061b2bd..3d4c464960bbce203dfe03debacbb40a5317802e 100644 (file)
 ///
 /// To link to [Something#Anchor!]
 pub struct SomeOtherType;
+
+/// Primitives?
+///
+/// [u32#hello]
+// @has anchors/fn.x.html
+// @has - '//a/@href' '{{channel}}/std/primitive.u32.html#hello'
+pub fn x() {}
+
+/// [prim@usize#x]
+// @has anchors/usize/index.html
+// @has - '//a/@href' '{{channel}}/std/primitive.usize.html#x'
+pub mod usize {}
index 54e986be9eccf2b2094796f2e68a9471070a3ebb..92cfd46188b015eba5d86c5d2420b0f976abc562 100644 (file)
@@ -2,6 +2,10 @@
 #![no_core]
 #![crate_type="rlib"]
 
+#[doc(primitive = "char")]
+/// Some char docs
+mod char {}
+
 #[lang = "char"]
 impl char {
     pub fn len_utf8(self) -> usize {
index 9347d7bb42819fed336d62de936f83f16a62276d..5a92a28556eded64fb62281464527a128d3027af 100644 (file)
@@ -9,8 +9,8 @@
 #![crate_type = "rlib"]
 
 // @has prim_methods_external_core/index.html
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
index 124faa9a636ffb9d3b3e979c3a21689b2a5f7b16..cfb3c3842ab161694f954813ddfa9823269ce9bf 100644 (file)
@@ -5,10 +5,13 @@
 
 
 // @has prim_methods_local/index.html
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
-//! A [`char`] and its [`char::len_utf8`].
+//! A [prim@`char`] and its [`char::len_utf8`].
+
+#[doc(primitive = "char")]
+mod char {}
 
 #[lang = "char"]
 impl char {
index 4744c84b6226db03b33a6b890fdb3e128878d34e..8c47f7ef77e5181e2d88e9d1d58aba86f9682ccf 100644 (file)
@@ -7,8 +7,8 @@
 /// [Self::f]
 /// [Self::MAX]
 // @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
 impl usize {
     /// Some docs
     pub fn f() {}
index 2af811ad5bbe8de6b320ab952f7f63be278649e3..f7f5052a36dd34329d3c218c0ad7a2c4fe183e7d 100644 (file)
@@ -1,5 +1,6 @@
 // aux-build:issue-15318.rs
 // ignore-cross-compile
+#![no_std]
 
 extern crate issue_15318;
 
diff --git a/src/test/rustdoc/issue-88600.rs b/src/test/rustdoc/issue-88600.rs
new file mode 100644 (file)
index 0000000..3761805
--- /dev/null
@@ -0,0 +1,34 @@
+// This test ensure that #[doc(hidden)] is applied correctly in enum variant fields.
+
+// Denotes a field which should be hidden.
+pub struct H;
+
+// Denotes a field which should not be hidden (shown).
+pub struct S;
+
+// @has issue_88600/enum.FooEnum.html
+pub enum FooEnum {
+    // @has - '//*[@id="variant.HiddenTupleItem"]//code' 'HiddenTupleItem(_)'
+    // @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0
+    HiddenTupleItem(#[doc(hidden)] H),
+    // @has - '//*[@id="variant.MultipleHidden"]//code' 'MultipleHidden(_, _)'
+    // @count - '//*[@id="variant.MultipleHidden.field.0"]' 0
+    // @count - '//*[@id="variant.MultipleHidden.field.1"]' 0
+    MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H),
+    // @has - '//*[@id="variant.MixedHiddenFirst"]//code' 'MixedHiddenFirst(_, S)'
+    // @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0
+    // @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S'
+    MixedHiddenFirst(#[doc(hidden)] H, S),
+    // @has - '//*[@id="variant.MixedHiddenLast"]//code' 'MixedHiddenLast(S, _)'
+    // @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S'
+    // @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0
+    MixedHiddenLast(S, #[doc(hidden)] H),
+    // @has - '//*[@id="variant.HiddenStruct"]//code' 'HiddenStruct'
+    // @count - '//*[@id="variant.HiddenStruct.field.h"]' 0
+    // @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S'
+    HiddenStruct {
+        #[doc(hidden)]
+        h: H,
+        s: S,
+    },
+}
diff --git a/src/test/rustdoc/no_std-primitive.rs b/src/test/rustdoc/no_std-primitive.rs
new file mode 100644 (file)
index 0000000..22fd392
--- /dev/null
@@ -0,0 +1,6 @@
+#![no_std]
+
+/// Link to [intra-doc link][u8]
+// @has 'no_std_primitive/fn.foo.html' '//a[@href="{{channel}}/core/primitive.u8.html"]' 'intra-doc link'
+// @has - '//a[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+pub fn foo() -> u8 {}
diff --git a/src/test/rustdoc/primitive/no_std.rs b/src/test/rustdoc/primitive/no_std.rs
new file mode 100644 (file)
index 0000000..f0f70cb
--- /dev/null
@@ -0,0 +1,16 @@
+#![no_std]
+#![deny(warnings)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link'
+/// Link to [primitive link][u8]
+pub fn foo() -> u8 {}
+
+// Test that all primitives can be linked to.
+/// [isize] [i8] [i16] [i32] [i64] [i128]
+/// [usize] [u8] [u16] [u32] [u64] [u128]
+/// [f32] [f64]
+/// [char] [bool] [str] [slice] [array] [tuple] [unit]
+/// [pointer] [reference] [fn] [never]
+pub fn bar() {}
index f727c9a47f2687095f84cf8929affbc71a57a515..16ab876e829ef8f25f4d82d79529e4c89c84f3ca 100644 (file)
@@ -10,7 +10,7 @@ unsafe impl<T> Send for Inner<T>
 
 // @has no_redundancy/struct.Outer.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Outer<T> where T: Copy + Send"
+// "impl<T> Send for Outer<T> where T: Send + Copy"
 pub struct Outer<T> {
     inner_field: Inner<T>,
 }
diff --git a/src/test/rustdoc/table-in-docblock.rs b/src/test/rustdoc/table-in-docblock.rs
new file mode 100644 (file)
index 0000000..858b589
--- /dev/null
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @count - '//*[@class="docblock"]/div/table' 2
+// @!has - '//*[@class="docblock"]/table'
+/// | hello | hello2 |
+/// | ----- | ------ |
+/// | data  | data2  |
+pub struct Foo;
+
+impl Foo {
+    /// | hello | hello2 |
+    /// | ----- | ------ |
+    /// | data  | data2  |
+    pub fn foo(&self) {}
+}
index 55905e5ca6a5acdeb03027ff80c5661a5584dcb7..bb60c898e8122a160a54b0055618050433cace6c 100644 (file)
@@ -8,15 +8,15 @@ LL |     fn foo(i32);
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn foo(self: i32);
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn foo(i32: TypeName);
-   |            ~~~~~~~~~~~~~
+   |               ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn foo(_: i32);
-   |            ~~~~~~
+   |            ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:9:29
@@ -28,7 +28,7 @@ LL |     fn foo_with_ref(&mut i32);
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn foo_with_ref(self: &mut i32);
-   |                     ~~~~~~~~~~~~~~
+   |                     +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn foo_with_ref(i32: &mut TypeName);
@@ -36,7 +36,7 @@ LL |     fn foo_with_ref(i32: &mut TypeName);
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn foo_with_ref(_: &mut i32);
-   |                     ~~~~~~~~~~~
+   |                     ++
 
 error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:12:47
@@ -96,15 +96,15 @@ LL |     fn bar_with_default_impl(String, String) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn bar_with_default_impl(self: String, String) {}
-   |                              ~~~~~~~~~~~~
+   |                              +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String: TypeName, String) {}
-   |                              ~~~~~~~~~~~~~~~~
+   |                                    ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar_with_default_impl(_: String, String) {}
-   |                              ~~~~~~~~~
+   |                              ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:22:44
@@ -116,11 +116,11 @@ LL |     fn bar_with_default_impl(String, String) {}
 help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String, String: TypeName) {}
-   |                                      ~~~~~~~~~~~~~~~~
+   |                                            ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar_with_default_impl(String, _: String) {}
-   |                                      ~~~~~~~~~
+   |                                      ++
 
 error: expected one of `:`, `@`, or `|`, found `,`
   --> $DIR/anon-params-denied-2018.rs:27:22
@@ -132,11 +132,11 @@ LL |     fn baz(a:usize, b, c: usize) -> usize {
 help: if this is a parameter name, give it a type
    |
 LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
-   |                     ~~~~~~~~~~~
+   |                      ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn baz(a:usize, _: b, c: usize) -> usize {
-   |                     ~~~~
+   |                     ++
 
 error: aborting due to 9 previous errors
 
index 12236960179e9f57c9fb9b8501031eebfeee7255..4d8022ecba73c5d3744a31d1ffd3f8ed298e1ec3 100644 (file)
@@ -2,6 +2,7 @@
 
 // Test binary_search_by_key lifetime. Issue #34683
 
+#[allow(dead_code)]
 #[derive(Debug)]
 struct Assignment {
     topic: String,
index 3ec3c72d38d72c53277581d6267fdaf353e898db..fa14c52cf0ad7f9fcd43549989d2bbf52d14b4e1 100644 (file)
@@ -76,6 +76,12 @@ fn main() {
         //~^ ERROR asm template must be a string literal
         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
         //~^ ERROR asm template must be a string literal
+        asm!("{}", in(reg) _);
+        //~^ ERROR _ cannot be used for input operands
+        asm!("{}", inout(reg) _);
+        //~^ ERROR _ cannot be used for input operands
+        asm!("{}", inlateout(reg) _);
+        //~^ ERROR _ cannot be used for input operands
     }
 }
 
index 423003c99d42c93fd4fe759a85312e059c040965..78d342cc1daf79f6fbf455b234501276d0a83858 100644 (file)
@@ -214,62 +214,80 @@ LL |         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:79:28
+   |
+LL |         asm!("{}", in(reg) _);
+   |                            ^
+
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:81:31
+   |
+LL |         asm!("{}", inout(reg) _);
+   |                               ^
+
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:83:35
+   |
+LL |         asm!("{}", inlateout(reg) _);
+   |                                   ^
+
 error: requires at least a template string argument
-  --> $DIR/parse-error.rs:84:1
+  --> $DIR/parse-error.rs:90:1
    |
 LL | global_asm!();
    | ^^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:86:13
+  --> $DIR/parse-error.rs:92:13
    |
 LL | global_asm!(FOO);
    |             ^^^
 
 error: expected token: `,`
-  --> $DIR/parse-error.rs:88:18
+  --> $DIR/parse-error.rs:94:18
    |
 LL | global_asm!("{}" FOO);
    |                  ^^^ expected `,`
 
 error: expected operand, options, or additional template string
-  --> $DIR/parse-error.rs:90:19
+  --> $DIR/parse-error.rs:96:19
    |
 LL | global_asm!("{}", FOO);
    |                   ^^^ expected operand, options, or additional template string
 
 error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:92:24
+  --> $DIR/parse-error.rs:98:24
    |
 LL | global_asm!("{}", const);
    |                        ^ expected expression
 
 error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
-  --> $DIR/parse-error.rs:94:30
+  --> $DIR/parse-error.rs:100:30
    |
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:96:25
+  --> $DIR/parse-error.rs:102:25
    |
 LL | global_asm!("", options(FOO));
    |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:98:25
+  --> $DIR/parse-error.rs:104:25
    |
 LL | global_asm!("", options(nomem FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:100:25
+  --> $DIR/parse-error.rs:106:25
    |
 LL | global_asm!("", options(nomem, FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: arguments are not allowed after options
-  --> $DIR/parse-error.rs:102:30
+  --> $DIR/parse-error.rs:108:30
    |
 LL | global_asm!("{}", options(), const FOO);
    |                   ---------  ^^^^^^^^^ argument
@@ -277,25 +295,25 @@ LL | global_asm!("{}", options(), const FOO);
    |                   previous options
 
 error: expected string literal
-  --> $DIR/parse-error.rs:104:29
+  --> $DIR/parse-error.rs:110:29
    |
 LL | global_asm!("", clobber_abi(FOO));
    |                             ^^^ not a string literal
 
 error: expected `)`, found `FOO`
-  --> $DIR/parse-error.rs:106:33
+  --> $DIR/parse-error.rs:112:33
    |
 LL | global_asm!("", clobber_abi("C" FOO));
    |                                 ^^^ expected `)`
 
 error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:108:32
+  --> $DIR/parse-error.rs:114:32
    |
 LL | global_asm!("", clobber_abi("C", FOO));
    |                                ^ expected `)`
 
 error: arguments are not allowed after clobber_abi
-  --> $DIR/parse-error.rs:110:37
+  --> $DIR/parse-error.rs:116:37
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ----------------  ^^^^^^^^^ argument
@@ -303,13 +321,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   clobber_abi
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:110:19
+  --> $DIR/parse-error.rs:116:19
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ^^^^^^^^^^^^^^^^
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:113:28
+  --> $DIR/parse-error.rs:119:28
    |
 LL | global_asm!("", options(), clobber_abi("C"));
    |                 ---------  ^^^^^^^^^^^^^^^^
@@ -317,7 +335,7 @@ LL | global_asm!("", options(), clobber_abi("C"));
    |                 options
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:115:30
+  --> $DIR/parse-error.rs:121:30
    |
 LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   ---------  ^^^^^^^^^^^^^^^^
@@ -325,7 +343,7 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   options
 
 error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:117:35
+  --> $DIR/parse-error.rs:123:35
    |
 LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
    |                 ----------------  ^^^^^^^^^^^^^^^^
@@ -333,7 +351,7 @@ LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
    |                 clobber_abi previously specified here
 
 error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:119:35
+  --> $DIR/parse-error.rs:125:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    -------------  ^^^^^^^^^^^^^ duplicate argument
@@ -341,7 +359,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    previously here
 
 error: argument never used
-  --> $DIR/parse-error.rs:119:35
+  --> $DIR/parse-error.rs:125:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                                   ^^^^^^^^^^^^^ argument never used
@@ -349,19 +367,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `""`
-  --> $DIR/parse-error.rs:122:28
+  --> $DIR/parse-error.rs:128:28
    |
 LL | global_asm!("", options(), "");
    |                            ^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
-  --> $DIR/parse-error.rs:124:30
+  --> $DIR/parse-error.rs:130:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
    |                              ^^^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:126:13
+  --> $DIR/parse-error.rs:132:13
    |
 LL | global_asm!(format!("{{{}}}", 0), const FOO);
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -369,7 +387,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:128:20
+  --> $DIR/parse-error.rs:134:20
    |
 LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -439,6 +457,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                                          ^^^ non-constant value
 
-error: aborting due to 63 previous errors
+error: aborting due to 66 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
index 7b4594108246b9b1eec19431cf5cd22ac97f7435..fc949f24948574619af48ab1e4a0ddd21541bea7 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | impl dyn Trait {
    |      ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `N` 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/associated-const-in-trait.rs:6:11
    |
@@ -12,6 +11,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     const N: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `N` to another trait
 
 error: aborting due to previous error
 
index 77915a80a79b07713b60cd863739a309aa3be642..7b158f1d754740ad1500dbaf5f7146e48085e045 100644 (file)
@@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | impl dyn Bar {}
    |      ^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` 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/issue-48027.rs:2:11
    |
@@ -29,6 +28,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
 
 error: aborting due to 2 previous errors
 
index 474b3c5c717c44fb55a2d1abc8de5134007692fe..19fc2f652c6be1907ee73b5ae7f6ea9cab45d205 100644 (file)
@@ -13,11 +13,11 @@ LL | fn a<C:Vehicle+Box>(_: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Box>::Color) {
-   |                        ~~~~~~~~~~~~~~~~~
+   |                        ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Vehicle>::Color) {
-   |                        ~~~~~~~~~~~~~~~~~~~~~
+   |                        ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `C`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12
@@ -34,11 +34,11 @@ LL | fn b<C>(_: C::Color) where C : Vehicle+Box {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Box>::Color) where C : Vehicle+Box {
-   |            ~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Vehicle>::Color) where C : Vehicle+Box {
-   |            ~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `C`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12
@@ -55,11 +55,11 @@ LL | fn c<C>(_: C::Color) where C : Vehicle, C : Box {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Box>::Color) where C : Vehicle, C : Box {
-   |            ~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Vehicle>::Color) where C : Vehicle, C : Box {
-   |            ~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20
@@ -76,11 +76,11 @@ LL |     fn e(&self, _: X::Color) where X : Box;
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Box>::Color) where X : Box;
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Vehicle>::Color) where X : Box;
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20
@@ -97,11 +97,11 @@ LL |     fn f(&self, _: X::Color) where X : Box { }
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Box>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Vehicle>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20
@@ -118,11 +118,11 @@ LL |     fn d(&self, _: X::Color) where X : Box { }
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Box>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Vehicle>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
index e6e95336bb53d56e523bbaae93739ee8ef7862cd..66a4899c77fef706e4fd36606b2993e42535f0d2 100644 (file)
@@ -21,11 +21,11 @@ LL | fn dent<C:BoxCar>(c: C, color: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Vehicle>::Color) {
-   |                                ~~~~~~~~~~~~~~~~~~~~~
+   |                                ~~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
-   |                                ~~~~~~~~~~~~~~~~~
+   |                                ~~~~~~~~~~~~
 
 error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar`
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37
@@ -74,11 +74,11 @@ LL | fn paint<C:BoxCar>(c: C, d: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Vehicle>::Color) {
-   |                             ~~~~~~~~~~~~~~~~~~~~~
+   |                             ~~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
-   |                             ~~~~~~~~~~~~~~~~~
+   |                             ~~~~~~~~~~~~
 
 error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32
index edcd2bf85adb64cc932e0914afc746faa7ce2ecb..e66c6b35ca1eed0749a494c4f95d889d19c8fea6 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
   --> $DIR/associated-types-bound-failure.rs:19:19
    |
 LL |     ToInt::to_int(&g.get())
-   |                   ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+   |     ------------- ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `ToInt::to_int`
   --> $DIR/associated-types-bound-failure.rs:6:5
index 8f94b24e7b6b616cf74d5ff948e211f6b18bafd9..6512d60b2c2951ab28c2c3c329e3aa2b0012c870 100644 (file)
@@ -19,11 +19,11 @@ LL | pub fn f2<T: Foo + Bar>(a: T, x: T::A) {}
 help: use fully qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Bar>::A) {}
-   |                                  ~~~~~~~~~~~~~
+   |                                  ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Foo>::A) {}
-   |                                  ~~~~~~~~~~~~~
+   |                                  ~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index c993e1d27202d5a53ac33f843623d48b8bd24852..912dedfdcebbc3b220401347f2191c494eb02f5a 100644 (file)
@@ -28,13 +28,11 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
index c4ea4ae6bc0cbb31987fde4786ddd4315054207b..15a5245d54d9577c52a6350962400918138c6670 100644 (file)
@@ -7,13 +7,15 @@ LL |     f1(2i32, 4i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     f1(2i32, 4u32);
-   |              ~~~~
+   |               ~~~
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
+  --> $DIR/associated-types-path-2.rs:29:14
    |
 LL |     f1(2u32, 4u32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f1`
   --> $DIR/associated-types-path-2.rs:13:14
@@ -22,16 +24,12 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
-   |
-LL |     f1(2u32, 4u32);
-   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:5
+  --> $DIR/associated-types-path-2.rs:34:14
    |
 LL |     f1(2u32, 4i32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f1`
   --> $DIR/associated-types-path-2.rs:13:14
@@ -39,14 +37,8 @@ note: required by a bound in `f1`
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:5
-   |
-LL |     f1(2u32, 4i32);
-   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
 error[E0308]: mismatched types
-  --> $DIR/associated-types-path-2.rs:41:18
+  --> $DIR/associated-types-path-2.rs:39:18
    |
 LL |     let _: i32 = f2(2i32);
    |            ---   ^^^^^^^^ expected `i32`, found `u32`
@@ -56,9 +48,9 @@ LL |     let _: i32 = f2(2i32);
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     let _: i32 = f2(2i32).try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
index 989624bdd93e2dafe4d034f8b5fa7ff6024bcb92..c508006c3a49927c7e0957c59df8d232c0c64d9b 100644 (file)
@@ -2,7 +2,12 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic
   --> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8
    |
 LL |     x: I::A)
-   |        ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+   |        ^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     x: <I as Foo<&isize>>::A)
+   |        ~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
index d457f9f8468b45f3eab18a0e4c2a8b699e345712..48433b15286d4466678f795388bdd0cfa498fd4d 100644 (file)
@@ -2,13 +2,23 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic
   --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32
    |
 LL |     fn some_method(&self, arg: I::A);
-   |                                ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+   |                                ^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     fn some_method(&self, arg: <I as Foo<&isize>>::A);
+   |                                ~~~~~~~~~~~~~~~~~~~~
 
 error[E0212]: cannot use the associated type of a trait with uninferred generic parameters
   --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24
    |
 LL |     fn mango(&self) -> X::Assoc {
-   |                        ^^^^^^^^ help: use a fully qualified path with inferred lifetimes: `<X as Banana<'_>>::Assoc`
+   |                        ^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     fn mango(&self) -> <X as Banana<'_>>::Assoc {
+   |                        ~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/issue-19883.rs b/src/test/ui/associated-types/issue-19883.rs
new file mode 100644 (file)
index 0000000..5cf4220
--- /dev/null
@@ -0,0 +1,16 @@
+trait From<Src> {
+    type Output;
+
+    fn from(src: Src) -> <Self as From<Src>>::Output;
+}
+
+trait To: Sized {
+    fn to<Dst: From<Self>>(self) ->
+        <Dst as From<Self>>::Dst
+        //~^ ERROR cannot find associated type `Dst` in trait `From`
+    {
+        From::from(self)
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/issue-19883.stderr b/src/test/ui/associated-types/issue-19883.stderr
new file mode 100644 (file)
index 0000000..bd6a86b
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0576]: cannot find associated type `Dst` in trait `From`
+  --> $DIR/issue-19883.rs:9:30
+   |
+LL |     type Output;
+   |     ------------ associated type `Output` defined here
+...
+LL |         <Dst as From<Self>>::Dst
+   |                              ^^^
+   |                              |
+   |                              not found in `From`
+   |                              help: maybe you meant this associated type: `Output`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0576`.
diff --git a/src/test/ui/associated-types/issue-21363.rs b/src/test/ui/associated-types/issue-21363.rs
new file mode 100644 (file)
index 0000000..acc28cb
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+// pretty-expanded FIXME #23616
+
+#![no_implicit_prelude]
+
+trait Iterator {
+    type Item;
+    fn dummy(&self) { }
+}
+
+impl<'a, T> Iterator for &'a mut (dyn Iterator<Item=T> + 'a) {
+    type Item = T;
+}
+
+fn main() {}
index e36572740f6551b39081018dacde8ca49ed120c8..22daaf329102a5a7624c5b71634cfb7c6bdab1d9 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-27675-unchecked-bounds.rs:15:31
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |                               ^ the trait `Copy` is not implemented for `T`
+   |     ------------------------- ^ the trait `Copy` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `copy`
   --> $DIR/issue-27675-unchecked-bounds.rs:10:12
diff --git a/src/test/ui/async-await/auxiliary/issue-72470-lib.rs b/src/test/ui/async-await/auxiliary/issue-72470-lib.rs
new file mode 100644 (file)
index 0000000..8383eba
--- /dev/null
@@ -0,0 +1,175 @@
+// compile-flags: -C opt-level=3
+// edition:2018
+
+use std::future::Future;
+use std::marker::PhantomData;
+use std::pin::Pin;
+use std::sync::atomic::AtomicUsize;
+use std::sync::Arc;
+use std::task::Poll::{Pending, Ready};
+use std::task::Waker;
+use std::task::{Context, Poll};
+use std::{
+    ptr,
+    task::{RawWaker, RawWakerVTable},
+};
+
+/// Future for the [`poll_fn`] function.
+pub struct PollFn<F> {
+    f: F,
+}
+
+impl<F> Unpin for PollFn<F> {}
+
+/// Creates a new future wrapping around a function returning [`Poll`].
+pub fn poll_fn<T, F>(f: F) -> PollFn<F>
+where
+    F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+    PollFn { f }
+}
+
+impl<T, F> Future for PollFn<F>
+where
+    F: FnMut(&mut Context<'_>) -> Poll<T>,
+{
+    type Output = T;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
+        (&mut self.f)(cx)
+    }
+}
+pub fn run<F: Future>(future: F) -> F::Output {
+    BasicScheduler.block_on(future)
+}
+
+pub(crate) struct BasicScheduler;
+
+impl BasicScheduler {
+    pub(crate) fn block_on<F>(&mut self, mut future: F) -> F::Output
+    where
+        F: Future,
+    {
+        let waker = unsafe { Waker::from_raw(raw_waker()) };
+        let mut cx = std::task::Context::from_waker(&waker);
+
+        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+
+        loop {
+            if let Ready(v) = future.as_mut().poll(&mut cx) {
+                return v;
+            }
+        }
+    }
+}
+
+// ===== impl Spawner =====
+
+fn raw_waker() -> RawWaker {
+    RawWaker::new(ptr::null(), waker_vtable())
+}
+
+fn waker_vtable() -> &'static RawWakerVTable {
+    &RawWakerVTable::new(
+        clone_arc_raw,
+        wake_arc_raw,
+        wake_by_ref_arc_raw,
+        drop_arc_raw,
+    )
+}
+
+unsafe fn clone_arc_raw(_: *const ()) -> RawWaker {
+    raw_waker()
+}
+
+unsafe fn wake_arc_raw(_: *const ()) {}
+
+unsafe fn wake_by_ref_arc_raw(_: *const ()) {}
+
+unsafe fn drop_arc_raw(_: *const ()) {}
+
+struct AtomicWaker {}
+
+impl AtomicWaker {
+    /// Create an `AtomicWaker`
+    fn new() -> AtomicWaker {
+        AtomicWaker {}
+    }
+
+    fn register_by_ref(&self, _waker: &Waker) {}
+}
+
+#[allow(dead_code)]
+struct Tx<T> {
+    inner: Arc<Chan<T>>,
+}
+
+struct Rx<T> {
+    inner: Arc<Chan<T>>,
+}
+
+#[allow(dead_code)]
+struct Chan<T> {
+    tx: PhantomData<T>,
+    semaphore: Sema,
+    rx_waker: AtomicWaker,
+    rx_closed: bool,
+}
+
+fn channel<T>() -> (Tx<T>, Rx<T>) {
+    let chan = Arc::new(Chan {
+        tx: PhantomData,
+        semaphore: Sema(AtomicUsize::new(0)),
+        rx_waker: AtomicWaker::new(),
+        rx_closed: false,
+    });
+
+    (
+        Tx {
+            inner: chan.clone(),
+        },
+        Rx { inner: chan },
+    )
+}
+
+// ===== impl Rx =====
+
+impl<T> Rx<T> {
+    /// Receive the next value
+    fn recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
+        self.inner.rx_waker.register_by_ref(cx.waker());
+
+        if self.inner.rx_closed && self.inner.semaphore.is_idle() {
+            Ready(None)
+        } else {
+            Pending
+        }
+    }
+}
+
+struct Sema(AtomicUsize);
+
+impl Sema {
+    fn is_idle(&self) -> bool {
+        false
+    }
+}
+
+pub struct UnboundedReceiver<T> {
+    chan: Rx<T>,
+}
+
+pub fn unbounded_channel<T>() -> UnboundedReceiver<T> {
+    let (tx, rx) = channel();
+
+    drop(tx);
+    let rx = UnboundedReceiver { chan: rx };
+
+    rx
+}
+
+impl<T> UnboundedReceiver<T> {
+    pub async fn recv(&mut self) -> Option<T> {
+        poll_fn(|cx| self.chan.recv(cx)).await
+    }
+}
index b79b6bc449233ab86c1a1f8cbb1b763ffc457021..919abf646037deaa2bcd7ceae1f8aa14e4214d1f 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Option<&str>: AsRef<Path>` is not satisfied
   --> $DIR/issue-72442.rs:12:36
    |
 LL |             let mut f = File::open(path.to_str())?;
-   |                                    ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+   |                         ---------- ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+   |                         |
+   |                         required by a bound introduced by this call
    |
 note: required by a bound in `File::open`
   --> $SRC_DIR/std/src/fs.rs:LL:COL
diff --git a/src/test/ui/async-await/issue-72470-llvm-dominate.rs b/src/test/ui/async-await/issue-72470-llvm-dominate.rs
new file mode 100644 (file)
index 0000000..5bb69a0
--- /dev/null
@@ -0,0 +1,66 @@
+// compile-flags: -C opt-level=3
+// aux-build: issue-72470-lib.rs
+// edition:2018
+// build-pass
+
+// Regression test for issue #72470, using the minimization
+// in https://github.com/jonas-schievink/llvm-error
+
+extern crate issue_72470_lib;
+
+use std::future::Future;
+use std::pin::Pin;
+use std::sync::Mutex;
+use std::task::Poll::{Pending, Ready};
+
+#[allow(dead_code)]
+enum Msg {
+    A(Vec<()>),
+    B,
+}
+
+#[allow(dead_code)]
+enum Out {
+    _0(Option<Msg>),
+    Disabled,
+}
+
+#[allow(unused_must_use)]
+fn main() {
+    let mut rx = issue_72470_lib::unbounded_channel::<Msg>();
+    let entity = Mutex::new(());
+    issue_72470_lib::run(async move {
+        {
+            let output = {
+                let mut fut = rx.recv();
+                issue_72470_lib::poll_fn(|cx| {
+                    loop {
+                        let fut = unsafe { Pin::new_unchecked(&mut fut) };
+                        let out = match fut.poll(cx) {
+                            Ready(out) => out,
+                            Pending => {
+                                break;
+                            }
+                        };
+                        #[allow(unused_variables)]
+                        match &out {
+                            Some(_msg) => {}
+                            _ => break,
+                        }
+                        return Ready(Out::_0(out));
+                    }
+                    Ready(Out::_0(None))
+                })
+                .await
+            };
+            match output {
+                Out::_0(Some(_msg)) => {
+                    entity.lock();
+                }
+                Out::_0(None) => unreachable!(),
+                _ => unreachable!(),
+            }
+        }
+        entity.lock();
+    });
+}
index 2456d6a147488e68f87b5db6fd10dc366d23388d..0ac2a39666966211d33f76bb25d06a289b937848 100644 (file)
@@ -1,20 +1,22 @@
 error: lifetime may not live long enough
-  --> $DIR/issue-76547.rs:19:14
+  --> $DIR/issue-76547.rs:20:13
    |
 LL | async fn fut(bufs: &mut [&mut [u8]]) {
-   |              ^^^^  -     - let's call the lifetime of this reference `'2`
-   |              |     |
-   |              |     let's call the lifetime of this reference `'1`
-   |              assignment requires that `'1` must outlive `'2`
+   |                    -     - let's call the lifetime of this reference `'2`
+   |                    |
+   |                    let's call the lifetime of this reference `'1`
+LL |     ListFut(bufs).await
+   |             ^^^^ this usage requires that `'1` must outlive `'2`
 
 error: lifetime may not live long enough
-  --> $DIR/issue-76547.rs:33:15
+  --> $DIR/issue-76547.rs:34:14
    |
 LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 {
-   |               ^^^^  -     - let's call the lifetime of this reference `'2`
-   |               |     |
-   |               |     let's call the lifetime of this reference `'1`
-   |               assignment requires that `'1` must outlive `'2`
+   |                     -     - let's call the lifetime of this reference `'2`
+   |                     |
+   |                     let's call the lifetime of this reference `'1`
+LL |     ListFut2(bufs).await
+   |              ^^^^ this usage requires that `'1` must outlive `'2`
 
 error: aborting due to 2 previous errors
 
index e39a049e2d30483e34ea8e9368f49ceff1249acb..0aea56ddb702b0386cec7e45011e04f1c4ec90bd 100644 (file)
@@ -2,9 +2,14 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/issue-54752-async-block.rs:6:22
    |
 LL | fn main() { let _a = (async  { }); }
-   |                      ^^^^^^^^^^^^ help: remove these parentheses
+   |                      ^          ^
    |
    = note: `#[warn(unused_parens)]` on by default
+help: remove these parentheses
+   |
+LL - fn main() { let _a = (async  { }); }
+LL + fn main() { let _a = async  { }; }
+   | 
 
 warning: 1 warning emitted
 
index 1dbf5db6c32ed9bdae77c7c18787f270c9d003db..df2ca025705d3955fae6c9b1a0d7333e29f39684 100644 (file)
@@ -6,7 +6,6 @@ async fn copy() -> Result<()>
 //~^ ERROR this enum takes 2 generic arguments
 {
     Ok(())
-    //~^ ERROR type annotations needed
 }
 
 fn main() { }
index ff46bcb8983b34399dfe17292ca7b4325f3a3bd3..45f5ec40cd758b08f914aabdce72e0d85bd7996f 100644 (file)
@@ -16,13 +16,6 @@ help: add missing generic argument
 LL | async fn copy() -> Result<(), E>
    |                             +++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-65159.rs:8:5
-   |
-LL |     Ok(())
-   |     ^^ cannot infer type for type parameter `E` declared on the enum `Result`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0107, E0282.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/auxiliary/define-macro.rs b/src/test/ui/auxiliary/define-macro.rs
deleted file mode 100644 (file)
index 4956907..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#[macro_export]
-macro_rules! define_macro {
-    ($i:ident) => {
-        macro_rules! $i { () => {} }
-    }
-}
diff --git a/src/test/ui/auxiliary/issue-72470-lib.rs b/src/test/ui/auxiliary/issue-72470-lib.rs
deleted file mode 100644 (file)
index 8383eba..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-// compile-flags: -C opt-level=3
-// edition:2018
-
-use std::future::Future;
-use std::marker::PhantomData;
-use std::pin::Pin;
-use std::sync::atomic::AtomicUsize;
-use std::sync::Arc;
-use std::task::Poll::{Pending, Ready};
-use std::task::Waker;
-use std::task::{Context, Poll};
-use std::{
-    ptr,
-    task::{RawWaker, RawWakerVTable},
-};
-
-/// Future for the [`poll_fn`] function.
-pub struct PollFn<F> {
-    f: F,
-}
-
-impl<F> Unpin for PollFn<F> {}
-
-/// Creates a new future wrapping around a function returning [`Poll`].
-pub fn poll_fn<T, F>(f: F) -> PollFn<F>
-where
-    F: FnMut(&mut Context<'_>) -> Poll<T>,
-{
-    PollFn { f }
-}
-
-impl<T, F> Future for PollFn<F>
-where
-    F: FnMut(&mut Context<'_>) -> Poll<T>,
-{
-    type Output = T;
-
-    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
-        (&mut self.f)(cx)
-    }
-}
-pub fn run<F: Future>(future: F) -> F::Output {
-    BasicScheduler.block_on(future)
-}
-
-pub(crate) struct BasicScheduler;
-
-impl BasicScheduler {
-    pub(crate) fn block_on<F>(&mut self, mut future: F) -> F::Output
-    where
-        F: Future,
-    {
-        let waker = unsafe { Waker::from_raw(raw_waker()) };
-        let mut cx = std::task::Context::from_waker(&waker);
-
-        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-
-        loop {
-            if let Ready(v) = future.as_mut().poll(&mut cx) {
-                return v;
-            }
-        }
-    }
-}
-
-// ===== impl Spawner =====
-
-fn raw_waker() -> RawWaker {
-    RawWaker::new(ptr::null(), waker_vtable())
-}
-
-fn waker_vtable() -> &'static RawWakerVTable {
-    &RawWakerVTable::new(
-        clone_arc_raw,
-        wake_arc_raw,
-        wake_by_ref_arc_raw,
-        drop_arc_raw,
-    )
-}
-
-unsafe fn clone_arc_raw(_: *const ()) -> RawWaker {
-    raw_waker()
-}
-
-unsafe fn wake_arc_raw(_: *const ()) {}
-
-unsafe fn wake_by_ref_arc_raw(_: *const ()) {}
-
-unsafe fn drop_arc_raw(_: *const ()) {}
-
-struct AtomicWaker {}
-
-impl AtomicWaker {
-    /// Create an `AtomicWaker`
-    fn new() -> AtomicWaker {
-        AtomicWaker {}
-    }
-
-    fn register_by_ref(&self, _waker: &Waker) {}
-}
-
-#[allow(dead_code)]
-struct Tx<T> {
-    inner: Arc<Chan<T>>,
-}
-
-struct Rx<T> {
-    inner: Arc<Chan<T>>,
-}
-
-#[allow(dead_code)]
-struct Chan<T> {
-    tx: PhantomData<T>,
-    semaphore: Sema,
-    rx_waker: AtomicWaker,
-    rx_closed: bool,
-}
-
-fn channel<T>() -> (Tx<T>, Rx<T>) {
-    let chan = Arc::new(Chan {
-        tx: PhantomData,
-        semaphore: Sema(AtomicUsize::new(0)),
-        rx_waker: AtomicWaker::new(),
-        rx_closed: false,
-    });
-
-    (
-        Tx {
-            inner: chan.clone(),
-        },
-        Rx { inner: chan },
-    )
-}
-
-// ===== impl Rx =====
-
-impl<T> Rx<T> {
-    /// Receive the next value
-    fn recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<T>> {
-        self.inner.rx_waker.register_by_ref(cx.waker());
-
-        if self.inner.rx_closed && self.inner.semaphore.is_idle() {
-            Ready(None)
-        } else {
-            Pending
-        }
-    }
-}
-
-struct Sema(AtomicUsize);
-
-impl Sema {
-    fn is_idle(&self) -> bool {
-        false
-    }
-}
-
-pub struct UnboundedReceiver<T> {
-    chan: Rx<T>,
-}
-
-pub fn unbounded_channel<T>() -> UnboundedReceiver<T> {
-    let (tx, rx) = channel();
-
-    drop(tx);
-    let rx = UnboundedReceiver { chan: rx };
-
-    rx
-}
-
-impl<T> UnboundedReceiver<T> {
-    pub async fn recv(&mut self) -> Option<T> {
-        poll_fn(|cx| self.chan.recv(cx)).await
-    }
-}
index f73c787346d8cfddc97a77a6a4d0533e97589095..30e74c5ec950c6044205afe52d09947b2f0ca66e 100644 (file)
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
 LL |     let x = Box::new(0);
    |         - captured outer variable
 LL |     Box::new(|| x)
-   |                 ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |              ---^
+   |              |  |
+   |              |  move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |              captured by this `Fn` closure
 
 error: aborting due to previous error
 
index 628f206e0a89616cf7629b0ce1f6d5269c124820..05489cf18e7fc9a5b2ebc352536a4b1d7a46f8ea 100644 (file)
@@ -1,15 +1,18 @@
 error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
   --> $DIR/borrowck-move-by-capture.rs:9:29
    |
-LL |     let bar: Box<_> = box 3;
-   |         --- captured outer variable
-LL |     let _g = to_fn_mut(|| {
-LL |         let _h = to_fn_once(move || -> isize { *bar });
-   |                             ^^^^^^^^^^^^^^^^   ----
-   |                             |                  |
-   |                             |                  move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
-   |                             |                  move occurs due to use in closure
-   |                             move out of `bar` occurs here
+LL |       let bar: Box<_> = box 3;
+   |           --- captured outer variable
+LL |       let _g = to_fn_mut(|| {
+   |  ________________________-
+LL | |         let _h = to_fn_once(move || -> isize { *bar });
+   | |                             ^^^^^^^^^^^^^^^^   ----
+   | |                             |                  |
+   | |                             |                  move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
+   | |                             |                  move occurs due to use in closure
+   | |                             move out of `bar` occurs here
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error: aborting due to previous error
 
index fd0e346e2b42dee204376dcdd467c13bd0c46037..23ef975cbbca1a8b985f3c2bc77dc27dbd76f9dc 100644 (file)
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(dead_code)]
 #![deny(unused_mut)]
 
 #[derive(Debug)]
index 569769b8213bff69417fc07200b2a9ff175ac535..dd0320bc53ba7d79d1151e7b34ea1ba3e85d845a 100644 (file)
@@ -17,7 +17,6 @@ async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_> {
     //~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
     //~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
     LockedMarket(generator.lock().unwrap().buy())
-    //~^ ERROR cannot return value referencing temporary value
 }
 
 struct LockedMarket<T>(T);
index 4bd0667304397e0a7b8eb91280cc183c52bcf03b..d2b927fb664c66b1958dbdfd914b771b95b1d2d1 100644 (file)
@@ -7,7 +7,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
    |                                                           expected 0 lifetime arguments
    |
 note: struct defined here, with 0 lifetime parameters
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
    |
 LL | struct LockedMarket<T>(T);
    |        ^^^^^^^^^^^^
@@ -19,7 +19,7 @@ LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_>
    |                                                           ^^^^^^^^^^^^ expected 1 generic argument
    |
 note: struct defined here, with 1 generic parameter: `T`
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
    |
 LL | struct LockedMarket<T>(T);
    |        ^^^^^^^^^^^^ -
@@ -28,16 +28,6 @@ help: add missing generic argument
 LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
    |                                                                          +++
 
-error[E0515]: cannot return value referencing temporary value
-  --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
-   |
-LL |     LockedMarket(generator.lock().unwrap().buy())
-   |     ^^^^^^^^^^^^^-------------------------^^^^^^^
-   |     |            |
-   |     |            temporary value created here
-   |     returns a value referencing data owned by the current function
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0515.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/borrowck/issue-82462.nll.stderr b/src/test/ui/borrowck/issue-82462.nll.stderr
new file mode 100644 (file)
index 0000000..10497c3
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-82462.rs:18:9
+   |
+LL |     for x in DroppingSlice(&*v).iter() {
+   |              ------------------
+   |              |               |
+   |              |               immutable borrow occurs here
+   |              a temporary with access to the immutable borrow is created here ...
+LL |         v.push(*x);
+   |         ^ mutable borrow occurs here
+LL |         break;
+LL |     }
+   |     - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+   |
+LL |     };
+   |      +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/issue-82462.rs b/src/test/ui/borrowck/issue-82462.rs
new file mode 100644 (file)
index 0000000..5a3c642
--- /dev/null
@@ -0,0 +1,21 @@
+struct DroppingSlice<'a>(&'a [i32]);
+
+impl Drop for DroppingSlice<'_> {
+    fn drop(&mut self) {
+        println!("hi from slice");
+    }
+}
+
+impl DroppingSlice<'_> {
+    fn iter(&self) -> std::slice::Iter<'_, i32> {
+        self.0.iter()
+    }
+}
+
+fn main() {
+    let mut v = vec![1, 2, 3, 4];
+    for x in DroppingSlice(&*v).iter() {
+        v.push(*x); //~ERROR
+        break;
+    }
+}
diff --git a/src/test/ui/borrowck/issue-82462.stderr b/src/test/ui/borrowck/issue-82462.stderr
new file mode 100644 (file)
index 0000000..a2c291f
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-82462.rs:18:9
+   |
+LL |     for x in DroppingSlice(&*v).iter() {
+   |              ------------------
+   |              |               |
+   |              |               immutable borrow occurs here
+   |              a temporary with access to the immutable borrow is created here ...
+LL |         v.push(*x);
+   |         ^^^^^^^^^^ mutable borrow occurs here
+LL |         break;
+LL |     }
+   |     - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+   |
+LL |     };
+   |      +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.rs b/src/test/ui/borrowck/issue-87456-point-to-closure.rs
new file mode 100644 (file)
index 0000000..9fc12ba
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for #87456.
+
+fn take_mut(_val: impl FnMut()) {}
+
+fn main() {
+    let val = String::new();
+    //~^ NOTE: captured outer variable
+    take_mut(|| {
+    //~^ NOTE: captured by this `FnMut` closure
+        let _foo: String = val;
+        //~^ ERROR: cannot move out of `val`, a captured variable in an `FnMut` closure [E0507]
+        //~| NOTE: move occurs because
+    })
+}
diff --git a/src/test/ui/borrowck/issue-87456-point-to-closure.stderr b/src/test/ui/borrowck/issue-87456-point-to-closure.stderr
new file mode 100644 (file)
index 0000000..fd38ad7
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0507]: cannot move out of `val`, a captured variable in an `FnMut` closure
+  --> $DIR/issue-87456-point-to-closure.rs:10:28
+   |
+LL |       let val = String::new();
+   |           --- captured outer variable
+LL |
+LL |       take_mut(|| {
+   |  ______________-
+LL | |
+LL | |         let _foo: String = val;
+   | |                            ^^^
+   | |                            |
+   | |                            move occurs because `val` has type `String`, which does not implement the `Copy` trait
+   | |                            help: consider borrowing here: `&val`
+LL | |
+LL | |
+LL | |     })
+   | |_____- captured by this `FnMut` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index dbba33f018397738934faaccf342827c060fc37f..1663ce81d6cf446b5819502eb7b14b8f8c108884 100644 (file)
@@ -1,11 +1,15 @@
 error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
   --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:11:9
    |
-LL |     let y = vec![format!("World")];
-   |         - captured outer variable
-LL |     call(|| {
-LL |         y.into_iter();
-   |         ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
+LL |       let y = vec![format!("World")];
+   |           - captured outer variable
+LL |       call(|| {
+   |  __________-
+LL | |         y.into_iter();
+   | |         ^ move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
+LL | |
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error: aborting due to previous error
 
index 5e3b43a47eeeef69952049d75d122a9489cb600c..2f1dec9d2090c69f231e82a8cc6d9decf653f049 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/into-boxed-slice-fail.rs:7:35
    |
 LL |     let _ = Box::into_boxed_slice(boxed_slice);
-   |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by `Box::<T, A>::into_boxed_slice`
@@ -24,7 +26,9 @@ error[E0277]: the size for values of type `dyn Debug` cannot be known at compila
   --> $DIR/into-boxed-slice-fail.rs:11:35
    |
 LL |     let _ = Box::into_boxed_slice(boxed_trait);
-   |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by `Box::<T, A>::into_boxed_slice`
diff --git a/src/test/ui/bug-7183-generics.rs b/src/test/ui/bug-7183-generics.rs
deleted file mode 100644 (file)
index f53a173..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// run-pass
-
-trait Speak : Sized {
-    fn say(&self, s:&str) -> String;
-    fn hi(&self) -> String { hello(self) }
-}
-
-fn hello<S:Speak>(s:&S) -> String{
-    s.say("hello")
-}
-
-impl Speak for isize {
-    fn say(&self, s:&str) -> String {
-        format!("{}: {}", s, *self)
-    }
-}
-
-impl<T: Speak> Speak for Option<T> {
-    fn say(&self, s:&str) -> String {
-        match *self {
-            None => format!("{} - none", s),
-            Some(ref x) => { format!("something!{}", x.say(s)) }
-        }
-    }
-}
-
-
-pub fn main() {
-    assert_eq!(3.hi(), "hello: 3".to_string());
-    assert_eq!(Some(Some(3)).hi(),
-               "something!something!hello: 3".to_string());
-    assert_eq!(None::<isize>.hi(), "hello - none".to_string());
-
-    assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string());
-    assert_eq!(Some(3).hi(), "something!hello: 3".to_string());
-}
index a4a480ac64d7c213389d0289bb61b002be593dab..14d43c1474c575b92a3ed7ffd9655e6cca54a5a9 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `{float}: Bar` is not satisfied
   --> $DIR/type_inference.rs:27:14
    |
 LL |     only_bar(x);
-   |              ^ the trait `Bar` is not implemented for `{float}`
+   |     -------- ^ the trait `Bar` is not implemented for `{float}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <i32 as Bar>
index 6c77d0809673c4426c406dfb47e4338fdbe7c9ef..d4f230780436ea5c80e632223774bfb2dcbc5c94 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
   --> $DIR/closure-expected.rs:3:23
    |
 LL |     let y = x.or_else(4);
-   |                       ^ expected an `FnOnce<()>` closure, found `{integer}`
+   |               ------- ^ expected an `FnOnce<()>` closure, found `{integer}`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
index 1cc22fac35282217cf9a121bc11222a220e9fa66..3399bc0018e54526e78acde295f432ab094dcdec 100644 (file)
@@ -3,6 +3,7 @@
 // check-pass
 #![allow(unreachable_code)]
 #![warn(unused)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 struct Point {
index 4eac5a2d282b07b527e6cbe8f3fe0841e57591e2..74109772724a4ddd7f55f4161d2671378f7c7c0d 100644 (file)
@@ -1,5 +1,5 @@
 warning: value captured by `a` is never read
-  --> $DIR/liveness.rs:23:9
+  --> $DIR/liveness.rs:24:9
    |
 LL |         a = 1;
    |         ^
@@ -13,7 +13,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `a`
-  --> $DIR/liveness.rs:32:9
+  --> $DIR/liveness.rs:33:9
    |
 LL |         a += 1;
    |         ^
@@ -27,7 +27,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `a` is never read
-  --> $DIR/liveness.rs:52:9
+  --> $DIR/liveness.rs:53:9
    |
 LL |         a += 1;
    |         ^
@@ -35,7 +35,7 @@ LL |         a += 1;
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `a` is never read
-  --> $DIR/liveness.rs:76:13
+  --> $DIR/liveness.rs:77:13
    |
 LL |             a = Some("d1");
    |             ^
@@ -43,7 +43,7 @@ LL |             a = Some("d1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness.rs:84:13
+  --> $DIR/liveness.rs:85:13
    |
 LL |             b = Some("e1");
    |             ^
@@ -51,7 +51,7 @@ LL |             b = Some("e1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness.rs:86:13
+  --> $DIR/liveness.rs:87:13
    |
 LL |             b = Some("e2");
    |             ^
@@ -59,7 +59,7 @@ LL |             b = Some("e2");
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `b`
-  --> $DIR/liveness.rs:84:13
+  --> $DIR/liveness.rs:85:13
    |
 LL |             b = Some("e1");
    |             ^
index 10a7d07a1df99937e38e1a7aa4d05a62862f9e4d..465c9476ba65b1636532ab50c9b3650543242747 100644 (file)
@@ -2,6 +2,7 @@
 
 // check-pass
 #![warn(unused)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 struct MyStruct {
index f74303e3dd682672d8d13cdba48d6669ee40ad9f..11a440554f759b4a60a9ea096cba8eda9746fdfd 100644 (file)
@@ -1,5 +1,5 @@
 warning: value assigned to `a` is never read
-  --> $DIR/liveness_unintentional_copy.rs:19:9
+  --> $DIR/liveness_unintentional_copy.rs:20:9
    |
 LL |         a = s;
    |         ^
@@ -13,7 +13,7 @@ LL | #![warn(unused)]
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `a`
-  --> $DIR/liveness_unintentional_copy.rs:19:9
+  --> $DIR/liveness_unintentional_copy.rs:20:9
    |
 LL |         a = s;
    |         ^
@@ -27,7 +27,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `a`
-  --> $DIR/liveness_unintentional_copy.rs:35:9
+  --> $DIR/liveness_unintentional_copy.rs:36:9
    |
 LL |         a += x;
    |         ^
index 045fe78040a922e330fb926908e33ba64ec74f9a..ed222b3148f410c45433e7aa671e1f526707d1d8 100644 (file)
@@ -1,6 +1,7 @@
 // edition:2021
 //check-pass
 #![warn(unused)]
+#![allow(dead_code)]
 #![feature(rustc_attrs)]
 
 #[derive(Debug, Clone, Copy)]
index 8e4f91c27e224d5c82405b91621700c7193fd917..3f7ddf93f0697c821feeccdb47c6a0eccc4da1eb 100644 (file)
@@ -3,6 +3,8 @@
 
 // Test that we can use raw ptrs when using `capture_disjoint_fields`.
 
+#![allow(dead_code)]
+
 #[derive(Debug)]
 struct S {
     s: String,
index bfea4979decaefe31646bb1a044f6c6bd758ce00..1a40326d986c4124e4a765519ebc276e6d83c193 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `F` cannot be shared between threads safely
   --> $DIR/closure-bounds-subtype.rs:13:22
    |
 LL |     take_const_owned(f);
-   |                      ^ `F` cannot be shared between threads safely
+   |     ---------------- ^ `F` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `take_const_owned`
   --> $DIR/closure-bounds-subtype.rs:4:50
index ab035d03b056d0d9dbaaf74b2aa88328e42d3e21..4a47e0549155f9508223981beefcbd89c32958f2 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-i
   --> $DIR/coerce-unsafe-to-closure.rs:2:44
    |
 LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
-   |                                            ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   |                                        --- ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   |                                        |
+   |                                        required by a bound introduced by this call
    |
    = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
 
diff --git a/src/test/ui/closures/issue-78720.rs b/src/test/ui/closures/issue-78720.rs
new file mode 100644 (file)
index 0000000..4cdb9f4
--- /dev/null
@@ -0,0 +1,19 @@
+fn server() -> impl {
+//~^ ERROR at least one trait must be specified
+    ().map2(|| "")
+}
+
+trait FilterBase2 {
+    fn map2<F>(self, f: F) -> Map2<F> {}
+    //~^ ERROR mismatched types
+    //~^^ ERROR the size for values of type `Self` cannot be known at compilation time
+}
+
+struct Map2<Segment2> {
+    _func: F,
+    //~^ ERROR cannot find type `F` in this scope
+}
+
+impl<F> FilterBase2 for F {}
+
+fn main() {}
diff --git a/src/test/ui/closures/issue-78720.stderr b/src/test/ui/closures/issue-78720.stderr
new file mode 100644 (file)
index 0000000..3dd1387
--- /dev/null
@@ -0,0 +1,55 @@
+error: at least one trait must be specified
+  --> $DIR/issue-78720.rs:1:16
+   |
+LL | fn server() -> impl {
+   |                ^^^^
+
+error[E0412]: cannot find type `F` in this scope
+  --> $DIR/issue-78720.rs:13:12
+   |
+LL |     _func: F,
+   |            ^
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+   |
+help: a trait with a similar name exists
+   |
+LL |     _func: Fn,
+   |            ~~
+help: you might be missing a type parameter
+   |
+LL | struct Map2<Segment2, F> {
+   |                     +++
+
+error[E0308]: mismatched types
+  --> $DIR/issue-78720.rs:7:39
+   |
+LL |     fn map2<F>(self, f: F) -> Map2<F> {}
+   |                                       ^^ expected struct `Map2`, found `()`
+   |
+   = note: expected struct `Map2<F>`
+           found unit type `()`
+
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/issue-78720.rs:7:16
+   |
+LL |     fn map2<F>(self, f: F) -> Map2<F> {}
+   |                ^^^^ doesn't have a size known at compile-time
+   |
+   = help: unsized fn params are gated as an unstable feature
+help: consider further restricting `Self`
+   |
+LL |     fn map2<F>(self, f: F) -> Map2<F> where Self: Sized {}
+   |                                       +++++++++++++++++
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     fn map2<F>(&self, f: F) -> Map2<F> {}
+   |                +
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/coercion/issue-88097.rs b/src/test/ui/coercion/issue-88097.rs
new file mode 100644 (file)
index 0000000..e543e1b
--- /dev/null
@@ -0,0 +1,31 @@
+// In #88097, the compiler attempted to coerce a closure type to itself via
+// a function pointer, which caused an unnecessary error. Check that this
+// behavior has been fixed.
+
+// check-pass
+
+fn peculiar() -> impl Fn(u8) -> u8 {
+    return |x| x + 1
+}
+
+fn peculiar2() -> impl Fn(u8) -> u8 {
+    return |x| x + 1;
+}
+
+fn peculiar3() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    return f
+}
+
+fn peculiar4() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    f
+}
+
+fn peculiar5() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    let g = |x| x + 2;
+    return if true { f } else { g }
+}
+
+fn main() {}
index a2b779e29540b8f4353604b7d044a4426f13057e..e9090c1b6bcfb38f80ddf8628b5c388a679e72af 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object
 LL | impl NotObjectSafe for dyn NotObjectSafe { }
    |                        ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object
    |
-   = help: consider moving `eq` 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/coherence-impl-trait-for-trait-object-safe.rs:6:43
    |
@@ -12,6 +11,7 @@ LL | trait NotObjectSafe { fn eq(&self, other: Self); }
    |       -------------                       ^^^^ ...because method `eq` references the `Self` type in this parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: consider moving `eq` to another trait
 
 error: aborting due to previous error
 
index 51f6faab3c7e48bde89e253cb8a580fee7f0dfa0..9efb5dc75f4f0dc65b7c8538a78863f8c40c46e0 100644 (file)
@@ -8,6 +8,7 @@ LL | impl<A:Iterator> Foo<A::Item> for A { }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
    |
    = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
+   = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
 
 error: aborting due to previous error
 
index cf842b1908532479e514ac44cc8b055127bd451e..2e2dac288a1da9cd6131b10cd52b36185b4f264f 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
   --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13
    |
 LL |     takes_t(t);
-   |             ^ the trait `Trait` is not implemented for `&dyn Trait`
+   |     ------- ^ the trait `Trait` is not implemented for `&dyn Trait`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_t`
   --> $DIR/coherence-unsafe-trait-object-impl.rs:10:15
index f9e03151374a2190040f8d4d949c09436db6a90b..9d62281178c48c689b5900ebd0c105255b1420a8 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 use std::fmt::Debug;
 
 #[derive(Debug)]
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs
new file mode 100644 (file)
index 0000000..916d60c
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: u8>(a: [(); N as usize]) {
+    bar::<{ N as usize as usize }>();
+    //~^ error: unconstrained generic constant
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr
new file mode 100644 (file)
index 0000000..d48b639
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-consts-as-cast-5.rs:5:11
+   |
+LL |     bar::<{ N as usize as usize }>();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:`
+
+error: aborting due to previous error
+
index deb6f3bd12c1dfd7e558c361831298977299a1c3..9b3c32a93977906a7900691bc744ffb3c7fc4a7e 100644 (file)
@@ -10,7 +10,7 @@ error: overly complex generic constant
   --> $DIR/array-size-in-generic-struct-param.rs:19:15
    |
 LL |     arr: [u8; CFG.arr_size],
-   |               ^^^^^^^^^^^^ unsupported projection
+   |               ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 9f0b7252e8326ff2893c633d2ea735670ed8de3c..95dae4ecc0431c50915ae669d481376177510eac 100644 (file)
@@ -4,7 +4,7 @@ error: overly complex generic constant
 LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
    |                                   ^^^^-------^^
    |                                       |
-   |                                       unsupported rvalue
+   |                                       unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 5749defb3e12c679227424fb7eef06d8bf66ad61..c9f847995223abd909743e26980a13488c04b7c3 100644 (file)
@@ -2,9 +2,7 @@ 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
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -12,9 +10,7 @@ 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
+   |                                   ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 319e6c2c032a0e067bf9fd2009cfe3416fbc63f9..4e1d71f154558857424588c3d100d5591912d63c 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object
 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
    |
@@ -12,6 +11,7 @@ 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
+   = help: consider moving `test` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs
new file mode 100644 (file)
index 0000000..c0404d3
--- /dev/null
@@ -0,0 +1,35 @@
+#![feature(generic_const_exprs, adt_const_params, const_trait_impl)]
+#![allow(incomplete_features)]
+
+// test `N + N` unifies with explicit function calls for non-builtin-types
+#[derive(PartialEq, Eq)]
+struct Foo(u8);
+
+impl const std::ops::Add for Foo {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        self
+    }
+}
+
+struct Evaluatable<const N: Foo>;
+
+fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
+    bar::<{ std::ops::Add::add(N, N) }>();
+}
+
+fn bar<const N: Foo>() {}
+
+// test that `N + N` unifies with explicit function calls for builin-types
+struct Evaluatable2<const N: usize>;
+
+fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) {
+    bar2::<{ std::ops::Add::add(N, N) }>();
+    //~^ error: unconstrained generic constant
+    // FIXME(generic_const_exprs) make this not an error
+}
+
+fn bar2<const N: usize>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
new file mode 100644 (file)
index 0000000..d18c791
--- /dev/null
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/unify-op-with-fn-call.rs:28:12
+   |
+LL |     bar2::<{ std::ops::Add::add(N, N) }>();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:`
+
+error: aborting due to previous error
+
index 1687dbbcbe3f8c3fedef497409a5aec01dfb0586..3da91b19a5ed95c95dc85830599f0972d10a7de3 100644 (file)
@@ -2,9 +2,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:4:34
    |
 LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
+   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -12,9 +10,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:9:34
    |
 LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
+   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -22,9 +18,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:16:38
    |
 LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-   |                                      ^^------^^^^^
-   |                                        |
-   |                                        dead code
+   |                                      ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 5386ef56a245a8b1df56bb7e458bbc96dfe4625d..d7b52063dc4db24c8bfea069cb12a9a6b54a15c3 100644 (file)
@@ -2,9 +2,9 @@ error: overly complex generic constant
   --> $DIR/issue-67375.rs:7:17
    |
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |                 ^^^----------^^^^^^^^^^^^
-   |                    |
-   |                    unsupported rvalue
+   |                 ^^---------------^^^^^^^^
+   |                   |
+   |                   unsupported operation in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 118cf447c01e2aefaed3a6f0eef4986570fb875f..fe0351a829220368f24a0aaab9d6f0e40d93f76f 100644 (file)
@@ -5,11 +5,10 @@ LL |       A: [(); {
    |  _____________^
 LL | |
 LL | |         let x: Option<Box<Self>> = None;
-   | |                                    ---- unsupported rvalue
 LL | |
 LL | |         0
 LL | |     }],
-   | |_____^
+   | |_____^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
index 7cdfc9dfcdf5a2404ff2b095e37a9f1ed8acb9e1..c63857b2314e9422f5fe31f8f78409df45b212a2 100644 (file)
@@ -2,7 +2,9 @@ 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`
+   |     - ^^^ the trait `X` is not implemented for `&str`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `z`
   --> $DIR/issue-86530.rs:10:8
diff --git a/src/test/ui/const-generics/issues/issue-87493.rs b/src/test/ui/const-generics/issues/issue-87493.rs
new file mode 100644 (file)
index 0000000..d8599ab
--- /dev/null
@@ -0,0 +1,14 @@
+pub trait MyTrait {
+    type Assoc;
+}
+
+pub fn foo<S, T>(_s: S, _t: T)
+where
+    S: MyTrait,
+    T: MyTrait<Assoc == S::Assoc>,
+    //~^ ERROR: expected one of `,` or `>`, found `==`
+    //~| ERROR: this trait takes 0 generic arguments but 1 generic argument was supplied
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-87493.stderr b/src/test/ui/const-generics/issues/issue-87493.stderr
new file mode 100644 (file)
index 0000000..8f92eea
--- /dev/null
@@ -0,0 +1,28 @@
+error: expected one of `,` or `>`, found `==`
+  --> $DIR/issue-87493.rs:8:22
+   |
+LL |     T: MyTrait<Assoc == S::Assoc>,
+   |                      ^^ expected one of `,` or `>`
+   |
+help: if you meant to use an associated type binding, replace `==` with `=`
+   |
+LL |     T: MyTrait<Assoc = S::Assoc>,
+   |                      ~
+
+error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/issue-87493.rs:8:8
+   |
+LL |     T: MyTrait<Assoc == S::Assoc>,
+   |        ^^^^^^^------------------- help: remove these generics
+   |        |
+   |        expected 0 generic arguments
+   |
+note: trait defined here, with 0 generic parameters
+  --> $DIR/issue-87493.rs:1:11
+   |
+LL | pub trait MyTrait {
+   |           ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
index 02108d8596037315d86359153b0f1ea16b19c978..70bc64057989955b680543d003d4e2cf37f0a5e6 100644 (file)
@@ -7,7 +7,7 @@ LL |     assert_eq!(R.method::<1u16>(), 1);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     assert_eq!(R.method::<1u8>(), 1);
-   |                           ~~~
+   |                            ~~
 
 error: aborting due to previous error
 
index 02108d8596037315d86359153b0f1ea16b19c978..70bc64057989955b680543d003d4e2cf37f0a5e6 100644 (file)
@@ -7,7 +7,7 @@ LL |     assert_eq!(R.method::<1u16>(), 1);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     assert_eq!(R.method::<1u8>(), 1);
-   |                           ~~~
+   |                            ~~
 
 error: aborting due to previous error
 
index 5e1bace549241d30e94aa316f457865706e95153..533fcabd418228734b6a9d46dfb121ae6d643a09 100644 (file)
@@ -2,13 +2,18 @@ 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)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     let _: A<{ 7 }>;
+LL +     let _: A<7>;
+   | 
 
 warning: 1 warning emitted
 
index e4455d86a1440b7f183c7d96582f5557bcd6d5f2..100faded079d52ce37753bcc108dabb59231e91e 100644 (file)
 
 const X: () = std::unimplemented!();
 //~^ ERROR evaluation of constant value failed
-//
+
 const W: () = std::panic!(MSG);
 //~^ ERROR evaluation of constant value failed
 
+const W2: () = std::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
+
 const Z_CORE: () = core::panic!("cheese");
 //~^ ERROR evaluation of constant value failed
 
@@ -33,3 +36,6 @@
 
 const W_CORE: () = core::panic!(MSG);
 //~^ ERROR evaluation of constant value failed
+
+const W2_CORE: () = core::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
index c0c749ede56126084186ec71a2b79d34283794b8..e98e4a506c0d69cc7c42b39c90167a505c47c60c 100644 (file)
@@ -39,45 +39,61 @@ LL | const W: () = std::panic!(MSG);
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic.rs:22:20
+  --> $DIR/const_panic.rs:22:16
+   |
+LL | const W2: () = std::panic!("{}", MSG);
+   |                ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:22:16
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_panic.rs:25:20
    |
 LL | const Z_CORE: () = core::panic!("cheese");
-   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:22:20
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cheese', $DIR/const_panic.rs:25:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic.rs:25:21
+  --> $DIR/const_panic.rs:28:21
    |
 LL | const Z2_CORE: () = core::panic!();
-   |                     ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:25:21
+   |                     ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic.rs:28:21
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic.rs:28:20
+  --> $DIR/const_panic.rs:31:20
    |
 LL | const Y_CORE: () = core::unreachable!();
-   |                    ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:28:20
+   |                    ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic.rs:31:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic.rs:31:20
+  --> $DIR/const_panic.rs:34:20
    |
 LL | const X_CORE: () = core::unimplemented!();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:31:20
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic.rs:34:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic.rs:34:20
+  --> $DIR/const_panic.rs:37:20
    |
 LL | const W_CORE: () = core::panic!(MSG);
-   |                    ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:34:20
+   |                    ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:37:20
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_panic.rs:40:21
+   |
+LL | const W2_CORE: () = core::panic!("{}", MSG);
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic.rs:40:21
    |
    = 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 10 previous errors
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index daef34cd6a3062602ebd1a0d9e332a5d0f0408dc..9b8652a776e61ca31f41a6cbab4843036de8f1d7 100644 (file)
@@ -2,6 +2,8 @@
 #![feature(const_panic)]
 #![crate_type = "lib"]
 
+const MSG: &str = "hello";
+
 const A: () = std::panic!("blåhaj");
 //~^ ERROR evaluation of constant value failed
 
 const D: () = std::unimplemented!();
 //~^ ERROR evaluation of constant value failed
 
-const E: () = core::panic!("shark");
+const E: () = std::panic!("{}", MSG);
+//~^ ERROR evaluation of constant value failed
+
+const A_CORE: () = core::panic!("shark");
+//~^ ERROR evaluation of constant value failed
+
+const B_CORE: () = core::panic!();
 //~^ ERROR evaluation of constant value failed
 
-const F: () = core::panic!();
+const C_CORE: () = core::unreachable!();
 //~^ ERROR evaluation of constant value failed
 
-const G: () = core::unreachable!();
+const D_CORE: () = core::unimplemented!();
 //~^ ERROR evaluation of constant value failed
 
-const H: () = core::unimplemented!();
+const E_CORE: () = core::panic!("{}", MSG);
 //~^ ERROR evaluation of constant value failed
index c1bdab3693d11babcf1bb9f60b9371ed6546227b..9eb241ae8e59db6a620d785e56ffa01395bdb6f4 100644 (file)
@@ -1,67 +1,83 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:5:15
+  --> $DIR/const_panic_2021.rs:7:15
    |
 LL | const A: () = std::panic!("blåhaj");
-   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:5:15
+   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'blåhaj', $DIR/const_panic_2021.rs:7:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:8:15
+  --> $DIR/const_panic_2021.rs:10:15
    |
 LL | const B: () = std::panic!();
-   |               ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:8:15
+   |               ^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:10:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:11:15
+  --> $DIR/const_panic_2021.rs:13:15
    |
 LL | const C: () = std::unreachable!();
-   |               ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:11:15
+   |               ^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:13:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:14:15
+  --> $DIR/const_panic_2021.rs:16:15
    |
 LL | const D: () = std::unimplemented!();
-   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:14:15
+   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:16:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:17:15
+  --> $DIR/const_panic_2021.rs:19:15
    |
-LL | const E: () = core::panic!("shark");
-   |               ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:17:15
+LL | const E: () = std::panic!("{}", MSG);
+   |               ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:19:15
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:20:15
+  --> $DIR/const_panic_2021.rs:22:20
    |
-LL | const F: () = core::panic!();
-   |               ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:20:15
+LL | const A_CORE: () = core::panic!("shark");
+   |                    ^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'shark', $DIR/const_panic_2021.rs:22:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:23:15
+  --> $DIR/const_panic_2021.rs:25:20
    |
-LL | const G: () = core::unreachable!();
-   |               ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:23:15
+LL | const B_CORE: () = core::panic!();
+   |                    ^^^^^^^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/const_panic_2021.rs:25:20
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_panic_2021.rs:28:20
+   |
+LL | const C_CORE: () = core::unreachable!();
+   |                    ^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_2021.rs:28:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_panic_2021.rs:26:15
+  --> $DIR/const_panic_2021.rs:31:20
    |
-LL | const H: () = core::unimplemented!();
-   |               ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:26:15
+LL | const D_CORE: () = core::unimplemented!();
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'not implemented', $DIR/const_panic_2021.rs:31:20
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 8 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const_panic_2021.rs:34:20
+   |
+LL | const E_CORE: () = core::panic!("{}", MSG);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'hello', $DIR/const_panic_2021.rs:34:20
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index b1ef820d827b4b24fff5a6285550f80185f2a993..19c08b621442522b7d5ef316655d5476432312f5 100644 (file)
@@ -8,9 +8,9 @@
 const fn test1<T: std::ops::Add>() {}
 //[stock]~^ trait bounds
 const fn test2(_x: &dyn Send) {}
-//[stock]~^ trait bounds
+//[stock]~^ trait objects in const fn are unstable
 const fn test3() -> &'static dyn Send { loop {} }
-//[stock]~^ trait bounds
+//[stock]~^ trait objects in const fn are unstable
 
 
 #[rustc_error]
index 2ad45f3afde8f8d334a3ebf5c9416902379a739a..d652b5268a8bf3594c8743eab58ca184713245d2 100644 (file)
@@ -7,7 +7,7 @@ LL | const fn test1<T: std::ops::Add>() {}
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/const_fn_trait_bound.rs:10:16
    |
 LL | const fn test2(_x: &dyn Send) {}
@@ -16,7 +16,7 @@ LL | const fn test2(_x: &dyn Send) {}
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/const_fn_trait_bound.rs:12:21
    |
 LL | const fn test3() -> &'static dyn Send { loop {} }
diff --git a/src/test/ui/consts/issue-23833.rs b/src/test/ui/consts/issue-23833.rs
new file mode 100644 (file)
index 0000000..d4128fa
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+#![allow(unused_imports)]
+use std::fmt;
+
+const A_I8_T
+    : [u32; (i8::MAX as i8 - 1i8) as usize]
+    = [0; (i8::MAX as usize) - 1];
+
+fn main() {
+    foo(&A_I8_T[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
diff --git a/src/test/ui/consts/issue-34784.rs b/src/test/ui/consts/issue-34784.rs
new file mode 100644 (file)
index 0000000..98d9434
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+
+#![warn(pointer_structural_match)]
+#![allow(dead_code)]
+const C: *const u8 = &0;
+
+fn foo(x: *const u8) {
+    match x {
+        C => {}
+        _ => {}
+    }
+}
+
+const D: *const [u8; 4] = b"abcd";
+
+fn main() {
+    match D {
+        D => {}
+        _ => {}
+    }
+}
diff --git a/src/test/ui/consts/issue-89088.rs b/src/test/ui/consts/issue-89088.rs
new file mode 100644 (file)
index 0000000..40cc665
--- /dev/null
@@ -0,0 +1,22 @@
+// Regression test for the ICE described in #89088.
+
+// check-pass
+
+#![allow(indirect_structural_match)]
+use std::borrow::Cow;
+
+const FOO: &A = &A::Field(Cow::Borrowed("foo"));
+
+#[derive(PartialEq, Eq)]
+enum A {
+    Field(Cow<'static, str>)
+}
+
+fn main() {
+    let var = A::Field(Cow::Borrowed("bar"));
+
+    match &var {
+        FOO => todo!(),
+        _ => todo!()
+    }
+}
index bb525d57197789ad5b1ebfbd6a370b00e155e848..10347a02074ec56221053f5d095b13be2a1aac23 100644 (file)
@@ -130,16 +130,16 @@ const fn no_apit(_x: impl std::fmt::Debug) {}
 //~^ ERROR trait bounds other than `Sized`
 //~| ERROR destructor
 const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
 const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
 
 const fn no_unsafe() { unsafe {} }
 
 const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-//~^ ERROR trait bounds other than `Sized`
-//~| ERROR trait bounds other than `Sized`
-//~| ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
+//~| ERROR trait objects in const fn are unstable
+//~| ERROR trait objects in const fn are unstable
 
 const fn no_fn_ptrs(_x: fn()) {}
 //~^ ERROR function pointer
index fcbf39d38690b5861ddd04d8d04b3eb9a35d7905..1e275d77bac672e1820f3fd31d0c66f9fdae589a 100644 (file)
@@ -214,6 +214,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo(&self) {}
+   |     ------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -223,6 +226,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo2(&self) {}
+   |     -------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -232,6 +238,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo3(&self) {}
+   |     -------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -270,7 +279,7 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {}
    |                  |
    |                  constant functions cannot evaluate destructors
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn.rs:132:23
    |
 LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
@@ -279,7 +288,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {}
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn.rs:134:32
    |
 LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
@@ -288,29 +297,35 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn.rs:139:41
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn.rs:139:42
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn.rs:139:42
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
index 6ca1e59b3af106815ab316f2ceb094b9a3e6084a..1ab8253b414a3b7333052a6a44d3ff66fbbfceba 100644 (file)
@@ -7,9 +7,9 @@ struct HasDyn {
 const fn no_inner_dyn_trait(_x: Hide) {}
 const fn no_inner_dyn_trait2(x: Hide) {
     x.0.field;
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
 }
 const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-//~^ ERROR trait bounds other than `Sized`
+//~^ ERROR trait objects in const fn are unstable
 
 fn main() {}
index ce844a2f0716425574d4188d2ee02ed39833055c..6eec1df5aeca7ba9fb942827b42f7078ff287237 100644 (file)
@@ -1,17 +1,21 @@
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn_dyn.rs:9:5
    |
+LL | const fn no_inner_dyn_trait2(x: Hide) {
+   | ------------------------------------- function declared as const here
 LL |     x.0.field;
    |     ^^^^^^^^^
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
 
-error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
+error[E0658]: trait objects in const fn are unstable
   --> $DIR/min_const_fn_dyn.rs:12:66
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-   |                                                                  ^^
+   | -----------------------------------------                        ^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.rs b/src/test/ui/consts/refs_check_const_eq-issue-88384.rs
new file mode 100644 (file)
index 0000000..204d18e
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+#![feature(fn_traits)]
+#![feature(adt_const_params)]
+//~^ WARNING the feature `adt_const_params` is incomplete
+
+#[derive(PartialEq, Eq)]
+struct CompileTimeSettings{
+    hooks: &'static[fn()],
+}
+
+struct Foo<const T: CompileTimeSettings>;
+
+impl<const T: CompileTimeSettings> Foo<T> {
+    fn call_hooks(){
+    }
+}
+
+fn main(){
+    const SETTINGS: CompileTimeSettings = CompileTimeSettings{
+        hooks: &[],
+    };
+
+    Foo::<SETTINGS>::call_hooks();
+}
diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
new file mode 100644 (file)
index 0000000..55928b4
--- /dev/null
@@ -0,0 +1,11 @@
+warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/refs_check_const_eq-issue-88384.rs:4:12
+   |
+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
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs b/src/test/ui/consts/refs_check_const_value_eq-issue-88876.rs
new file mode 100644 (file)
index 0000000..6ce9da4
--- /dev/null
@@ -0,0 +1,12 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(adt_const_params)]
+
+struct FooConst<const ARRAY: &'static [&'static str]> {}
+
+const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"];
+
+fn main() {
+    let _ = FooConst::<FOO_ARR> {};
+}
diff --git a/src/test/ui/derives/clone-debug-dead-code.rs b/src/test/ui/derives/clone-debug-dead-code.rs
new file mode 100644 (file)
index 0000000..80e9132
--- /dev/null
@@ -0,0 +1,45 @@
+// Checks that derived implementations of Clone and Debug do not
+// contribute to dead code analysis (issue #84647).
+
+#![forbid(dead_code)]
+
+struct A { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Clone)]
+struct B { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug)]
+struct C { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug,Clone)]
+struct D { f: () }
+//~^ ERROR: field is never read: `f`
+
+struct E { f: () }
+//~^ ERROR: field is never read: `f`
+// Custom impl, still doesn't read f
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self { f: () }
+    }
+}
+
+struct F { f: () }
+// Custom impl that actually reads f
+impl Clone for F {
+    fn clone(&self) -> Self {
+        Self { f: self.f }
+    }
+}
+
+fn main() {
+    let _ = A { f: () };
+    let _ = B { f: () };
+    let _ = C { f: () };
+    let _ = D { f: () };
+    let _ = E { f: () };
+    let _ = F { f: () };
+}
diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr
new file mode 100644 (file)
index 0000000..226007f
--- /dev/null
@@ -0,0 +1,38 @@
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:6:12
+   |
+LL | struct A { f: () }
+   |            ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/clone-debug-dead-code.rs:4:11
+   |
+LL | #![forbid(dead_code)]
+   |           ^^^^^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:10:12
+   |
+LL | struct B { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:14:12
+   |
+LL | struct C { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:18:12
+   |
+LL | struct D { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:21:12
+   |
+LL | struct E { f: () }
+   |            ^^^^^
+
+error: aborting due to 5 previous errors
+
index ecdbbff4d97c3deec79819b0e95fb7f2c2513de1..2538b5533a6d69f57ee3218bdad585c269468994 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `C: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:13
    |
 LL |     is_copy(B { a: 1, b: C });
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Copy`
-   |             help: consider borrowing here: `&B { a: 1, b: C }`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Copy`
+   |     |       help: consider borrowing here: `&B { a: 1, b: C }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Copy` for `B<C>`
   --> $DIR/deriving-copyclone.rs:9:10
@@ -23,10 +24,11 @@ error[E0277]: the trait bound `C: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
    |
 LL |     is_clone(B { a: 1, b: C });
-   |              ^^^^^^^^^^^^^^^^
-   |              |
-   |              expected an implementor of trait `Clone`
-   |              help: consider borrowing here: `&B { a: 1, b: C }`
+   |     -------- ^^^^^^^^^^^^^^^^
+   |     |        |
+   |     |        expected an implementor of trait `Clone`
+   |     |        help: consider borrowing here: `&B { a: 1, b: C }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Clone` for `B<C>`
   --> $DIR/deriving-copyclone.rs:9:16
@@ -44,10 +46,11 @@ error[E0277]: the trait bound `D: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
    |
 LL |     is_copy(B { a: 1, b: D });
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Copy`
-   |             help: consider borrowing here: `&B { a: 1, b: D }`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Copy`
+   |     |       help: consider borrowing here: `&B { a: 1, b: D }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Copy` for `B<D>`
   --> $DIR/deriving-copyclone.rs:9:10
index f6e105555fd9d739e88c7931b242216c6bb27c6b..4374d1594e4655272a53e3ffd9c7961fd430d574 100644 (file)
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S<T> {
     foo: (),
index 7b0a1d20260d4565a221c714101386c7a81dfd95..b93cbe5f8b6fd2b15a0a96f9f6467cf315f32af0 100644 (file)
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S {
     _int: isize,
index 166f1be55e02afd2d4f55e2cdacdd8113aa40da8..7ad3f03471324e6b179a29a5629c6b44d49e61c8 100644 (file)
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S((), ());
 
index 8931e94a4f8d2487e06782c341c38b336f5db6a4..07f91d059735623a416b00b41898211089c05bbb 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 pub fn main() {
     #[derive(Debug)]
     struct Foo {
diff --git a/src/test/ui/deriving/issue-3935.rs b/src/test/ui/deriving/issue-3935.rs
new file mode 100644 (file)
index 0000000..e98d68e
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+
+#[derive(PartialEq)]
+struct Bike {
+    name: String,
+}
+
+pub fn main() {
+    let town_bike = Bike { name: "schwinn".to_string() };
+    let my_bike = Bike { name: "surly".to_string() };
+
+    assert!(town_bike != my_bike);
+}
index fcb4ea1d592b589d81bbeb0a174890e993335348..c7458916c536492e9b7da88fa3de4b435fefe4fd 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:24:21
    |
 LL |     Foo::<i32>::bar(&1i8);
-   |                     ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+   |     --------------- ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <i8 as Foo<bool>>
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
    |
 LL |     Foo::<i32>::bar(&1u8);
-   |                     ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+   |     --------------- ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <u8 as Foo<bool>>
@@ -37,7 +41,9 @@ error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:26:21
    |
 LL |     Foo::<i32>::bar(&true);
-   |                     ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+   |     --------------- ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <bool as Foo<bool>>
diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs
new file mode 100644 (file)
index 0000000..53dad85
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {}
+
+const FOO: [u8; 3] = { //~ ERROR this code is interpreted as a block expression
+    1, 2, 3
+};
+
+const BAR: [&str; 3] = {"one", "two", "three"};
+//~^ ERROR this code is interpreted as a block expression
+
+fn foo() {
+    {1, 2, 3};
+    //~^ ERROR this code is interpreted as a block expression
+}
+
+fn bar() {
+    1, 2, 3 //~ ERROR expected one of
+}
diff --git a/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr b/src/test/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr
new file mode 100644 (file)
index 0000000..9ab491f
--- /dev/null
@@ -0,0 +1,49 @@
+error: this code is interpreted as a block expression, not an array
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22
+   |
+LL |   const FOO: [u8; 3] = {
+   |  ______________________^
+LL | |     1, 2, 3
+LL | | };
+   | |_^
+   |
+   = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+   |
+LL ~ const FOO: [u8; 3] = [
+LL |     1, 2, 3
+LL ~ ];
+   |
+
+error: this code is interpreted as a block expression, not an array
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:7:24
+   |
+LL | const BAR: [&str; 3] = {"one", "two", "three"};
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+   |
+LL | const BAR: [&str; 3] = ["one", "two", "three"];
+   |                        ~                     ~
+
+error: this code is interpreted as a block expression, not an array
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:11:5
+   |
+LL |     {1, 2, 3};
+   |     ^^^^^^^^^
+   |
+   = note: to define an array, one would use square brackets instead of curly braces
+help: try using [] instead of {}
+   |
+LL |     [1, 2, 3];
+   |     ~       ~
+
+error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
+  --> $DIR/issue-87830-try-brackets-for-arrays.rs:16:6
+   |
+LL |     1, 2, 3
+   |      ^ expected one of `.`, `;`, `?`, `}`, or an operator
+
+error: aborting due to 4 previous errors
+
index 3d8049cba9c8f822adde19927c649193d72a7bd7..27f516341ee315a98f81efc7a7ba9aaa81c2a0d7 100644 (file)
@@ -7,7 +7,7 @@ LL |         OhNo = 0_u8,
 help: change the type of the numeric literal from `u8` to `i8`
    |
 LL |         OhNo = 0_i8,
-   |                ~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:28:16
@@ -18,7 +18,7 @@ LL |         OhNo = 0_i8,
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |         OhNo = 0_u8,
-   |                ~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:41:16
@@ -29,7 +29,7 @@ LL |         OhNo = 0_u16,
 help: change the type of the numeric literal from `u16` to `i16`
    |
 LL |         OhNo = 0_i16,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:54:16
@@ -40,7 +40,7 @@ LL |         OhNo = 0_i16,
 help: change the type of the numeric literal from `i16` to `u16`
    |
 LL |         OhNo = 0_u16,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:67:16
@@ -51,7 +51,7 @@ LL |         OhNo = 0_u32,
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |         OhNo = 0_i32,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:80:16
@@ -62,7 +62,7 @@ LL |         OhNo = 0_i32,
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |         OhNo = 0_u32,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:93:16
@@ -73,7 +73,7 @@ LL |         OhNo = 0_u64,
 help: change the type of the numeric literal from `u64` to `i64`
    |
 LL |         OhNo = 0_i64,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:106:16
@@ -84,7 +84,7 @@ LL |         OhNo = 0_i64,
 help: change the type of the numeric literal from `i64` to `u64`
    |
 LL |         OhNo = 0_u64,
-   |                ~~~~~
+   |                  ~~~
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/enable-unstable-lib-feature.rs b/src/test/ui/enable-unstable-lib-feature.rs
deleted file mode 100644 (file)
index aa6a973..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Test that enabling an unstable feature disables warnings
-
-// aux-build:stability-cfg2.rs
-
-#![feature(unstable_test_feature)]
-#![deny(non_snake_case)] // To trigger a hard error
-
-// Shouldn't generate a warning about unstable features
-extern crate stability_cfg2;
-
-pub fn BOGUS() { } //~ ERROR
-
-pub fn main() { }
diff --git a/src/test/ui/enable-unstable-lib-feature.stderr b/src/test/ui/enable-unstable-lib-feature.stderr
deleted file mode 100644 (file)
index bb4e928..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: function `BOGUS` should have a snake case name
-  --> $DIR/enable-unstable-lib-feature.rs:11:8
-   |
-LL | pub fn BOGUS() { }
-   |        ^^^^^ help: convert the identifier to snake case: `bogus`
-   |
-note: the lint level is defined here
-  --> $DIR/enable-unstable-lib-feature.rs:6:9
-   |
-LL | #![deny(non_snake_case)] // To trigger a hard error
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/enum-discriminant/niche-prefer-zero.rs b/src/test/ui/enum-discriminant/niche-prefer-zero.rs
new file mode 100644 (file)
index 0000000..f20607a
--- /dev/null
@@ -0,0 +1,14 @@
+// Check that niche selection prefers zero.
+// See https://github.com/rust-lang/rust/pull/87794
+// run-pass
+#[repr(u8)]
+pub enum Size {
+    One = 1,
+    Two = 2,
+    Three = 3,
+}
+
+fn main() {
+    // check that `None` is zero
+    assert_eq!(0, unsafe { std::mem::transmute::<Option<Size>, u8>(None) });
+}
index cead9776e4abb3a4a4d96319cbc747a6d84df428..3773d6f5234b0ca88cc8aafef6e7598d02733606 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | fn call_foo(x: Box<dyn Trait>) {
    |                    ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/E0038.rs:2:22
    |
@@ -12,6 +11,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn foo(&self) -> Self;
    |                      ^^^^ ...because method `foo` references the `Self` type in its return type
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
index 86966d520e7e2653c3ada4bc53132161b90edf5c..f3dbf122de3baa73ec1e4af724187343af15938c 100644 (file)
@@ -13,11 +13,11 @@ LL |         let _: Self::A;
 help: use fully qualified syntax to disambiguate
    |
 LL |         let _: <Self as Foo>::A;
-   |                ~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |         let _: <Self as Bar>::A;
-   |                ~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Err` in bounds of `Self`
   --> $DIR/E0221.rs:21:16
@@ -26,12 +26,13 @@ LL |     type Err: T3;
    |     ------------- ambiguous `Err` from `My`
 LL |     fn test() {
 LL |         let _: Self::Err;
-   |                ^^^^^^^^^
-   |                |
-   |                ambiguous associated type `Err`
-   |                help: use fully qualified syntax to disambiguate: `<Self as My>::Err`
+   |                ^^^^^^^^^ ambiguous associated type `Err`
    |
    = note: associated type `Self` could derive from `FromStr`
+help: use fully qualified syntax to disambiguate
+   |
+LL |         let _: <Self as My>::Err;
+   |                ~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
index c82665aa580ba326f44bd1a35ed97b6f4cc806e0..2b4784d7eccbd5ed8258814c2c53d72d327ff1f6 100644 (file)
@@ -16,7 +16,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/E0277.rs:15:15
    |
 LL |     some_func(5i32);
-   |               ^^^^ the trait `Foo` is not implemented for `i32`
+   |     --------- ^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `some_func`
   --> $DIR/E0277.rs:7:17
diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs
deleted file mode 100644 (file)
index 86e9cb5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(platform_intrinsics)]
-
-extern "platform-intrinsic" {
-    fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
-}
-
-fn main () {
-}
diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr
deleted file mode 100644 (file)
index 8021f7d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle`
-  --> $DIR/E0439.rs:4:5
-   |
-LL |     fn simd_shuffle<A,B>(a: A, b: A, c: [u32; 8]) -> B;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0439`.
index 8c6025e708e8ae395d534198c03c1fac1483b925..637eb27db01e675a5e847493bba30295dacacfef 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/error-should-say-copy-not-pod.rs:6:17
    |
 LL |     check_bound("nocopy".to_string());
-   |                 ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check_bound`
   --> $DIR/error-should-say-copy-not-pod.rs:3:18
diff --git a/src/test/ui/expr-empty-ret.rs b/src/test/ui/expr-empty-ret.rs
deleted file mode 100644 (file)
index ce8ffaf..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-// Issue #521
-
-// pretty-expanded FIXME #23616
-
-fn f() {
-    let _x = match true {
-        true => { 10 }
-        false => { return }
-    };
-}
-
-pub fn main() { }
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed b/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed
new file mode 100644 (file)
index 0000000..c50b9a1
--- /dev/null
@@ -0,0 +1,19 @@
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+    let num = 5;
+    (1..num).reduce(|a, b| {
+        //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+        println!("{}", a);
+        a * b
+    }).unwrap();
+}
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs b/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs
new file mode 100644 (file)
index 0000000..58c81f3
--- /dev/null
@@ -0,0 +1,19 @@
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+    let num = 5;
+    (1..num).reduce(|a, b|
+        //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+        println!("{}", a);
+        a * b
+    ).unwrap();
+}
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr b/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr
new file mode 100644 (file)
index 0000000..dac9a8c
--- /dev/null
@@ -0,0 +1,38 @@
+error: closure bodies that contain statements must be surrounded by braces
+  --> $DIR/missing_braces_around_block.rs:14:26
+   |
+LL |     (1..num).reduce(|a, b|
+   |                          ^
+...
+LL |     ).unwrap();
+   |     ^
+   |
+note: statement found outside of a block
+  --> $DIR/missing_braces_around_block.rs:16:26
+   |
+LL |         println!("{}", a);
+   |         -----------------^ this `;` turns the preceding closure into a statement
+   |         |
+   |         this expression is a statement because of the trailing semicolon
+note: the closure body may be incorrectly delimited
+  --> $DIR/missing_braces_around_block.rs:14:21
+   |
+LL |       (1..num).reduce(|a, b|
+   |  _____________________^
+LL | |
+LL | |         println!("{}", a);
+   | |_________________________^ this is the parsed closure...
+LL |           a * b
+LL |       ).unwrap();
+   |       - ...but likely you meant the closure to end here
+help: try adding braces
+   |
+LL ~     (1..num).reduce(|a, b| {
+LL |
+LL |         println!("{}", a);
+LL |         a * b
+LL ~     }).unwrap();
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs
new file mode 100644 (file)
index 0000000..e4341e1
--- /dev/null
@@ -0,0 +1,16 @@
+// Part of issue #27300.
+// The problem here is that ruby-style closures are parsed as blocks whose
+// first statement is a closure. See the issue for more details:
+// https://github.com/rust-lang/rust/issues/27300
+
+// Note: this test represents what the compiler currently emits. The error
+// message will be improved later.
+
+fn main() {
+    let p = Some(45).and_then({
+        //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+        |x| println!("doubling {}", x);
+        Some(x * 2)
+        //~^ ERROR: cannot find value `x` in this scope
+    });
+}
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
new file mode 100644 (file)
index 0000000..14d28b5
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/ruby_style_closure.rs:13:14
+   |
+LL |         Some(x * 2)
+   |              ^ not found in this scope
+
+error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+  --> $DIR/ruby_style_closure.rs:10:31
+   |
+LL |       let p = Some(45).and_then({
+   |  ______________________--------_^
+   | |                      |
+   | |                      required by a bound introduced by this call
+LL | |
+LL | |         |x| println!("doubling {}", x);
+LL | |         Some(x * 2)
+   | |         -----------
+LL | |
+LL | |     });
+   | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
+   |
+   = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
index 74981ebb76c932952b92f7c31cb87c89ca5311fb..c6f0d5df9b53b3ba44a5f93e32ed5e5232a9da74 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `extern "C" fn() {f}`
   --> $DIR/extern-wrong-value-type.rs:9:11
    |
 LL |     is_fn(f);
-   |           ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+   |     ----- ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
index a3bd65e518e4ced281311b20597432e9f9daadbe..72cb4cc843cc42b746e5f30127a4d0913256ce3b 100644 (file)
@@ -40,7 +40,6 @@ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
 LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
    |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8
    |
@@ -48,6 +47,7 @@ LL | trait NonObjectSafe3 {
    |       -------------- this trait cannot be made into an object...
 LL |     fn foo<T>(&self);
    |        ^^^ ...because method `foo` has generic type parameters
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:35
@@ -55,7 +55,6 @@ error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
 LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22
    |
@@ -63,6 +62,7 @@ LL | trait NonObjectSafe4 {
    |       -------------- this trait cannot be made into an object...
 LL |     fn foo(&self, s: &Self);
    |                      ^^^^^ ...because method `foo` references the `Self` type in this parameter
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16
diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs b/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs
deleted file mode 100644 (file)
index bd815db..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-struct Foo {
-    foo: u8,
-    _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~^ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~| ERROR anonymous unions are unimplemented
-        bar: u8,
-        baz: u16
-    }
-}
-
-union Bar {
-    foobar: u8,
-    _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~^ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~| ERROR anonymous structs are unimplemented
-    //~| ERROR unions may not contain fields that need dropping [E0740]
-        foobaz: u8,
-        barbaz: u16
-    }
-}
-
-struct S;
-struct Baz {
-    _: S //~ ERROR unnamed fields are not yet fully implemented [E0658]
-}
-
-fn main(){}
diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr b/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr
deleted file mode 100644 (file)
index 4f3ab85..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:5
-   |
-LL |     _: union {
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:8
-   |
-LL |       _: union {
-   |  ________^
-LL | |
-LL | |
-LL | |         bar: u8,
-LL | |         baz: u16
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL |     _: struct {
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:8
-   |
-LL |       _: struct {
-   |  ________^
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:24:5
-   |
-LL |     _: S
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error: anonymous unions are unimplemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:8
-   |
-LL |       _: union {
-   |  ________^
-LL | |
-LL | |
-LL | |         bar: u8,
-LL | |         baz: u16
-LL | |     }
-   | |_____^
-
-error: anonymous structs are unimplemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:8
-   |
-LL |       _: struct {
-   |  ________^
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL | /     _: struct {
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL | /     _: struct {
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0658, E0740.
-For more information about an error, try `rustc --explain E0658`.
index fbb18c8c4909705c058429ac44f851f9bcfd99e5..0f7520ef7f8a95a80644466eedf36a0a5902a143 100644 (file)
@@ -12,10 +12,10 @@ LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:24:5
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |     ^^^ doesn't have a size known at compile-time
+   |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = note: all function arguments must have a statically known size
index 263b5e594e10cc0130dc7a3d30a5d4e90317ae87..454373c322e9b15367f7dc67552e0643b4285dd3 100644 (file)
@@ -19,7 +19,7 @@ LL |     let y: f32 = 1f64;
 help: change the type of the numeric literal from `f64` to `f32`
    |
 LL |     let y: f32 = 1f32;
-   |                  ~~~~
+   |                   ~~~
 
 error: aborting due to 2 previous errors
 
index 57a25b8e48b351c7988ff5943ab9b088296e6344..f9fb3a0ef267dbfbd50bfe9f30ecb29ad43c4848 100644 (file)
@@ -35,7 +35,9 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `{integer}`
   --> $DIR/fn-trait-formatting.rs:19:14
    |
 LL |     needs_fn(1);
-   |              ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+   |     -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
 note: required by a bound in `needs_fn`
diff --git a/src/test/ui/generator/issue-88653.rs b/src/test/ui/generator/issue-88653.rs
new file mode 100644 (file)
index 0000000..ce9159b
--- /dev/null
@@ -0,0 +1,19 @@
+// Regression test for #88653, where a confusing warning about a
+// type mismatch in generator arguments was issued.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn foo(bar: bool) -> impl Generator<(bool,)> {
+//~^ ERROR: type mismatch in generator arguments [E0631]
+//~| NOTE: expected signature of `fn((bool,)) -> _`
+    |bar| {
+    //~^ NOTE: found signature of `fn(bool) -> _`
+        if bar {
+            yield bar;
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/generator/issue-88653.stderr b/src/test/ui/generator/issue-88653.stderr
new file mode 100644 (file)
index 0000000..5bd8ad1
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0631]: type mismatch in generator arguments
+  --> $DIR/issue-88653.rs:8:22
+   |
+LL | fn foo(bar: bool) -> impl Generator<(bool,)> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `fn((bool,)) -> _`
+...
+LL |     |bar| {
+   |     ----- found signature of `fn(bool) -> _`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
index 7ae128d072dd9bca3120fc507baa34978c3f7a6d..4ae745b0ffeacae0b44f51142e7d37db5e1c0246 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` cannot b
   --> $DIR/static-not-unpin.rs:14:18
    |
 LL |     assert_unpin(generator);
-   |                  ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `assert_unpin`
index 8651789688eaa75d4f850b00e1a19382a6f23eb3..a55642490f975eda5797eef92446e1f5986b2859 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object
 LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
-   = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/gat-in-trait-path.rs:5:10
    |
@@ -12,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
 
 error: aborting due to previous error
 
index 01edad00a89f15408d93c5ae018360b569fb16b8..27c135cb7cf82abd5d9a41d7d61576ead8a8ab15 100644 (file)
@@ -15,7 +15,7 @@ impl<T> Foo for Fooy<T> {
     type A<'a> where Self: 'static = (&'a ());
     //~^ ERROR the parameter type `T` may not live long enough
     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-    //~^ ERROR lifetime bound not satisfied
+    //~^ ERROR `impl` associated type
     //~| ERROR lifetime bound not satisfied
     type C where Self: Copy = String;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
index 8cf923ca3ac0c4f0763029fc2da03b6f43ccd9ce..73415e0faac88898b8a28fe0958b0154206150f4 100644 (file)
@@ -5,24 +5,16 @@ LL |     type A<'a> where Self: 'static = (&'a ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
+   = note: ...so that the definition in impl matches the definition from the trait
 
-error[E0478]: lifetime bound not satisfied
+error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
   --> $DIR/impl_bounds.rs:17:5
    |
+LL |     type B<'a, 'b> where 'a: 'b;
+   |     ---------------------------- expected
+...
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
-  --> $DIR/impl_bounds.rs:17:16
-   |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |                ^^
-note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
-  --> $DIR/impl_bounds.rs:17:12
-   |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |            ^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error[E0478]: lifetime bound not satisfied
   --> $DIR/impl_bounds.rs:17:5
index b4b89ab047363ce28c2cf43558a2c455b4484b8a..7dd1bdf891eb572599764d9928fbbd4994cabe14 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `X` cannot be made into an object
 LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
    |
-   = help: consider moving `Y` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-67510-pass.rs:4:10
    |
@@ -12,6 +11,7 @@ LL | trait X {
    |       - this trait cannot be made into an object...
 LL |     type Y<'a>;
    |          ^ ...because it contains the generic associated type `Y`
+   = help: consider moving `Y` to another trait
 
 error: aborting due to previous error
 
index 246454f0612dbb76e22ae60bcde1171b89f31037..0a7eb5dde6009838b44af2b5c6ff9bc75bdb03bb 100644 (file)
@@ -20,7 +20,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
-   = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-76535.rs:6:10
    |
@@ -28,6 +27,7 @@ LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
 LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
   --> $DIR/issue-76535.rs:36:57
@@ -35,7 +35,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
-   = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-76535.rs:6:10
    |
@@ -43,6 +42,7 @@ LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
 LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
    = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
index b92730839568d47ea5543cf33aefb71a16e59bd0..17dd0ff4a0c94088a5bc09ecf56ed22a5a644bee 100644 (file)
@@ -20,7 +20,6 @@ error[E0038]: the trait `CollectionFamily` cannot be made into an object
 LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
    |
-   = help: consider moving `Member` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-78671.rs:4:10
    |
@@ -28,6 +27,7 @@ LL | trait CollectionFamily {
    |       ---------------- this trait cannot be made into an object...
 LL |     type Member<T>;
    |          ^^^^^^ ...because it contains the generic associated type `Member`
+   = help: consider moving `Member` to another trait
 
 error: aborting due to 2 previous errors
 
index 8d8ef6bf836854602bd1ca900d411280b70c4c85..b6f856a97e7257fcc8c5a9795e024846ff4159f9 100644 (file)
@@ -20,7 +20,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
-   = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-79422.rs:20:10
    |
@@ -28,6 +27,7 @@ LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
 LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:41:13
@@ -35,7 +35,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object
 LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
-   = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-79422.rs:20:10
    |
@@ -43,6 +42,7 @@ LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
 LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
    = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
index 04cd84b08011c4c0aa56640767816d355081c25b..e1ff772921104a1cc506b48eb784dfdec5fa03f1 100644 (file)
@@ -9,7 +9,7 @@ LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
    | |                                    - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the type `<Left as HasChildrenOf>::T` will meet its required lifetime bounds
+   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
 
 error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
   --> $DIR/issue-86787.rs:23:5
@@ -22,7 +22,7 @@ LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
    | |                                    - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the type `<Right as HasChildrenOf>::T` will meet its required lifetime bounds
+   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
new file mode 100644 (file)
index 0000000..ad9f2e3
--- /dev/null
@@ -0,0 +1,13 @@
+// check-fail
+
+#![feature(generic_associated_types)]
+
+trait Foo {
+    type Assoc<'a, 'b>;
+}
+impl Foo for () {
+    type Assoc<'a, 'b> where 'a: 'b = ();
+    //~^ `impl` associated type
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
new file mode 100644 (file)
index 0000000..0e183c8
--- /dev/null
@@ -0,0 +1,11 @@
+error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
+  --> $DIR/missing-where-clause-on-trait.rs:9:5
+   |
+LL |     type Assoc<'a, 'b>;
+   |     ------------------- expected
+...
+LL |     type Assoc<'a, 'b> where 'a: 'b = ();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
+
+error: aborting due to previous error
+
index 6429bb8159e1f9899debc6bce4e7d442e6148a3e..5ab37910207ca8d78abbf0b45e13733af78a8bf5 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object
 LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
    |
-   = help: consider moving `Item` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/trait-objects.rs:4:10
    |
@@ -12,6 +11,7 @@ LL | trait StreamingIterator {
    |       ----------------- this trait cannot be made into an object...
 LL |     type Item<'a> where Self: 'a;
    |          ^^^^ ...because it contains the generic associated type `Item`
+   = help: consider moving `Item` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generics/mid-path-type-params.rs b/src/test/ui/generics/mid-path-type-params.rs
new file mode 100644 (file)
index 0000000..a812820
--- /dev/null
@@ -0,0 +1,37 @@
+// run-pass
+
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
+
+struct S<T> {
+    contents: T,
+}
+
+impl<T> S<T> {
+    fn new<U>(x: T, _: U) -> S<T> {
+        S {
+            contents: x,
+        }
+    }
+}
+
+trait Trait<T> {
+    fn new<U>(x: T, y: U) -> Self;
+}
+
+struct S2 {
+    contents: isize,
+}
+
+impl Trait<isize> for S2 {
+    fn new<U>(x: isize, _: U) -> S2 {
+        S2 {
+            contents: x,
+        }
+    }
+}
+
+pub fn main() {
+    let _ = S::<isize>::new::<f64>(1, 1.0);
+    let _: S2 = Trait::<isize>::new::<f64>(1, 1.0);
+}
diff --git a/src/test/ui/guards.rs b/src/test/ui/guards.rs
deleted file mode 100644 (file)
index 10a4bb6..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// run-pass
-
-#![allow(non_shorthand_field_patterns)]
-
-#[derive(Copy, Clone)]
-struct Pair { x: isize, y: isize }
-
-pub fn main() {
-    let a: isize =
-        match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } };
-    assert_eq!(a, 2);
-
-    let b: isize =
-        match (Pair {x: 10, y: 20}) {
-          x if x.x < 5 && x.y < 5 => { 1 }
-          Pair {x: x, y: y} if x == 10 && y == 20 => { 2 }
-          Pair {x: _x, y: _y} => { 3 }
-        };
-    assert_eq!(b, 2);
-}
index 8311c147ee3bdea371bdcee987ea3524697fdaee..b13226fef6e76fe7ada4ad5948fa3f7428d26faa 100644 (file)
@@ -1,11 +1,19 @@
 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) -> _`
+LL |       task(annotate(
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |
+LL | |         Annotate::<RefMutFamily<usize>>::new(),
+LL | |         |value: &mut usize| {
+   | |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+LL | |             *value = 2;
+LL | |         }
+LL | |     ));
+   | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
    |
 note: required by a bound in `annotate`
   --> $DIR/issue-62529-1.rs:44:8
@@ -20,7 +28,9 @@ error[E0277]: the size for values of type `impl Execute` cannot be known at comp
   --> $DIR/issue-62529-1.rs:80:10
    |
 LL |       task(annotate(
-   |  __________^
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
 LL | |
 LL | |
 LL | |         Annotate::<RefMutFamily<usize>>::new(),
@@ -44,7 +54,9 @@ error[E0277]: the trait bound `impl Execute: Execute` is not satisfied
   --> $DIR/issue-62529-1.rs:80:10
    |
 LL |       task(annotate(
-   |  __________^
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
 LL | |
 LL | |
 LL | |         Annotate::<RefMutFamily<usize>>::new(),
index d8267712c2b8a9c11b7a47b05419c2292d2f428e..8cda76b9490c2faa02aa7911ff42ab729a8f9e98 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
    |
 LL |     want_bar_for_any_ccx(b);
-   |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_bar_for_any_ccx`
   --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
index a510c05055c1481ae732838cd799181a7b31f21d..88793a1525bfb7ba98d4bb881f27108607c75698 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
    |
 LL |     want_foo_for_any_tcx(f);
-   |                          ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+   |     -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_foo_for_any_tcx`
   --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
    |
 LL |     want_bar_for_any_ccx(b);
-   |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_bar_for_any_ccx`
   --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
diff --git a/src/test/ui/hrtb/issue-88446.rs b/src/test/ui/hrtb/issue-88446.rs
new file mode 100644 (file)
index 0000000..571b853
--- /dev/null
@@ -0,0 +1,35 @@
+// check-pass
+
+trait Yokeable<'a> {
+    type Output: 'a;
+}
+impl<'a> Yokeable<'a> for () {
+    type Output = ();
+}
+
+trait DataMarker<'data> {
+    type Yokeable: for<'a> Yokeable<'a>;
+}
+impl<'data> DataMarker<'data> for () {
+    type Yokeable = ();
+}
+
+struct DataPayload<'data, M>(&'data M);
+
+impl DataPayload<'static, ()> {
+    pub fn map_project_with_capture<M2, T>(
+        _: for<'a> fn(
+            capture: T,
+            std::marker::PhantomData<&'a ()>,
+        ) -> <M2::Yokeable as Yokeable<'a>>::Output,
+    ) -> DataPayload<'static, M2>
+    where
+        M2: DataMarker<'static>,
+    {
+        todo!()
+    }
+}
+
+fn main() {
+    let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!());
+}
diff --git a/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.rs
new file mode 100644 (file)
index 0000000..ecfa5c6
--- /dev/null
@@ -0,0 +1,16 @@
+trait Foo {
+    type T;
+    fn foo(&self, t: Self::T);
+//~^ NOTE expected 0 type parameters
+}
+
+impl Foo for u32 {
+    type T = ();
+
+    fn foo(&self, t: impl Clone) {}
+//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+//~| NOTE found 1 type parameter
+//~| NOTE `impl Trait` introduces an implicit type parameter
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/impl-trait/type-arg-mismatch-due-to-impl-trait.stderr
new file mode 100644 (file)
index 0000000..30322f8
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
+   |
+LL |     fn foo(&self, t: Self::T);
+   |           - expected 0 type parameters
+...
+LL |     fn foo(&self, t: impl Clone) {}
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      found 1 type parameter
+   |                      `impl Trait` introduces an implicit type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
index 1bcb89de2bad4ad1f21e583334f9729d7f9a4895..24f42f22f37df661cd86629998e175b888af1ea4 100644 (file)
@@ -16,7 +16,7 @@ LL |     bar::<isize>(i);  // i should not be re-coerced back to an isize
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     bar::<isize>(i.try_into().unwrap());  // i should not be re-coerced back to an isize
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/inference/issue-71309.rs b/src/test/ui/inference/issue-71309.rs
new file mode 100644 (file)
index 0000000..c31107d
--- /dev/null
@@ -0,0 +1,7 @@
+fn foo(x: Result<i32, ()>) -> Result<(), ()> {
+    let y: u32 = x?;
+    //~^ ERROR: `?` operator has incompatible types
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/issue-71309.stderr b/src/test/ui/inference/issue-71309.stderr
new file mode 100644 (file)
index 0000000..af8714f
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0308]: `?` operator has incompatible types
+  --> $DIR/issue-71309.rs:2:18
+   |
+LL |     let y: u32 = x?;
+   |                  ^^ expected `u32`, found `i32`
+   |
+   = note: `?` operator cannot convert from `i32` to `u32`
+help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+   |
+LL |     let y: u32 = x?.try_into().unwrap();
+   |                    ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
index c9cfbc506be46c5199dea97b091f3851e304bec6..4c29c4a1cb05c6af7160603f4c854000470f7c15 100644 (file)
@@ -7,7 +7,7 @@ LL |     id_i8(a16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:41:11
@@ -18,7 +18,7 @@ LL |     id_i8(a32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:44:11
@@ -29,7 +29,7 @@ LL |     id_i8(a64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:47:11
@@ -40,16 +40,18 @@ LL |     id_i8(asize);
 help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(asize.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:51:12
    |
 LL |     id_i16(a8);
-   |            ^^
-   |            |
-   |            expected `i16`, found `i8`
-   |            help: you can convert an `i8` to an `i16`: `a8.into()`
+   |            ^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     id_i16(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:55:12
@@ -60,7 +62,7 @@ LL |     id_i16(a32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(a32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:58:12
@@ -71,7 +73,7 @@ LL |     id_i16(a64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(a64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:61:12
@@ -82,25 +84,29 @@ LL |     id_i16(asize);
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:65:12
    |
 LL |     id_i32(a8);
-   |            ^^
-   |            |
-   |            expected `i32`, found `i8`
-   |            help: you can convert an `i8` to an `i32`: `a8.into()`
+   |            ^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     id_i32(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:68:12
    |
 LL |     id_i32(a16);
-   |            ^^^
-   |            |
-   |            expected `i32`, found `i16`
-   |            help: you can convert an `i16` to an `i32`: `a16.into()`
+   |            ^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     id_i32(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:72:12
@@ -111,7 +117,7 @@ LL |     id_i32(a64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(a64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:75:12
@@ -122,34 +128,40 @@ LL |     id_i32(asize);
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:79:12
    |
 LL |     id_i64(a8);
-   |            ^^
-   |            |
-   |            expected `i64`, found `i8`
-   |            help: you can convert an `i8` to an `i64`: `a8.into()`
+   |            ^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     id_i64(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:82:12
    |
 LL |     id_i64(a16);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i16`
-   |            help: you can convert an `i16` to an `i64`: `a16.into()`
+   |            ^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     id_i64(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:85:12
    |
 LL |     id_i64(a32);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i32`
-   |            help: you can convert an `i32` to an `i64`: `a32.into()`
+   |            ^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     id_i64(a32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:89:12
@@ -160,25 +172,29 @@ LL |     id_i64(asize);
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     id_i64(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:93:14
    |
 LL |     id_isize(a8);
-   |              ^^
-   |              |
-   |              expected `isize`, found `i8`
-   |              help: you can convert an `i8` to an `isize`: `a8.into()`
+   |              ^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |     id_isize(a8.into());
+   |                +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:96:14
    |
 LL |     id_isize(a16);
-   |              ^^^
-   |              |
-   |              expected `isize`, found `i16`
-   |              help: you can convert an `i16` to an `isize`: `a16.into()`
+   |              ^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |     id_isize(a16.into());
+   |                 +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:99:14
@@ -189,7 +205,7 @@ LL |     id_isize(a32);
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     id_isize(a32.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:102:14
@@ -200,7 +216,7 @@ LL |     id_isize(a64);
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     id_isize(a64.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:108:11
@@ -211,7 +227,7 @@ LL |     id_i8(c16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:111:11
@@ -222,7 +238,7 @@ LL |     id_i8(c32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:114:11
@@ -233,16 +249,18 @@ LL |     id_i8(c64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:118:12
    |
 LL |     id_i16(c8);
-   |            ^^
-   |            |
-   |            expected `i16`, found `i8`
-   |            help: you can convert an `i8` to an `i16`: `c8.into()`
+   |            ^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     id_i16(c8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:122:12
@@ -253,7 +271,7 @@ LL |     id_i16(c32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(c32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:125:12
@@ -264,25 +282,29 @@ LL |     id_i16(c64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(c64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:129:12
    |
 LL |     id_i32(c8);
-   |            ^^
-   |            |
-   |            expected `i32`, found `i8`
-   |            help: you can convert an `i8` to an `i32`: `c8.into()`
+   |            ^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     id_i32(c8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:132:12
    |
 LL |     id_i32(c16);
-   |            ^^^
-   |            |
-   |            expected `i32`, found `i16`
-   |            help: you can convert an `i16` to an `i32`: `c16.into()`
+   |            ^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     id_i32(c16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:136:12
@@ -293,34 +315,40 @@ LL |     id_i32(c64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(c64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:140:12
    |
 LL |     id_i64(a8);
-   |            ^^
-   |            |
-   |            expected `i64`, found `i8`
-   |            help: you can convert an `i8` to an `i64`: `a8.into()`
+   |            ^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     id_i64(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:143:12
    |
 LL |     id_i64(a16);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i16`
-   |            help: you can convert an `i16` to an `i64`: `a16.into()`
+   |            ^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     id_i64(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:146:12
    |
 LL |     id_i64(a32);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i32`
-   |            help: you can convert an `i32` to an `i64`: `a32.into()`
+   |            ^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     id_i64(a32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:152:11
@@ -331,7 +359,7 @@ LL |     id_u8(b16);
 help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:155:11
@@ -342,7 +370,7 @@ LL |     id_u8(b32);
 help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:158:11
@@ -353,7 +381,7 @@ LL |     id_u8(b64);
 help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:161:11
@@ -364,16 +392,18 @@ LL |     id_u8(bsize);
 help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(bsize.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:165:12
    |
 LL |     id_u16(b8);
-   |            ^^
-   |            |
-   |            expected `u16`, found `u8`
-   |            help: you can convert a `u8` to a `u16`: `b8.into()`
+   |            ^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     id_u16(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:169:12
@@ -384,7 +414,7 @@ LL |     id_u16(b32);
 help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(b32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:172:12
@@ -395,7 +425,7 @@ LL |     id_u16(b64);
 help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(b64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:175:12
@@ -406,25 +436,29 @@ LL |     id_u16(bsize);
 help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:179:12
    |
 LL |     id_u32(b8);
-   |            ^^
-   |            |
-   |            expected `u32`, found `u8`
-   |            help: you can convert a `u8` to a `u32`: `b8.into()`
+   |            ^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |     id_u32(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:182:12
    |
 LL |     id_u32(b16);
-   |            ^^^
-   |            |
-   |            expected `u32`, found `u16`
-   |            help: you can convert a `u16` to a `u32`: `b16.into()`
+   |            ^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     id_u32(b16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:186:12
@@ -435,7 +469,7 @@ LL |     id_u32(b64);
 help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     id_u32(b64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:189:12
@@ -446,34 +480,40 @@ LL |     id_u32(bsize);
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     id_u32(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:193:12
    |
 LL |     id_u64(b8);
-   |            ^^
-   |            |
-   |            expected `u64`, found `u8`
-   |            help: you can convert a `u8` to a `u64`: `b8.into()`
+   |            ^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |     id_u64(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:196:12
    |
 LL |     id_u64(b16);
-   |            ^^^
-   |            |
-   |            expected `u64`, found `u16`
-   |            help: you can convert a `u16` to a `u64`: `b16.into()`
+   |            ^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |     id_u64(b16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:199:12
    |
 LL |     id_u64(b32);
-   |            ^^^
-   |            |
-   |            expected `u64`, found `u32`
-   |            help: you can convert a `u32` to a `u64`: `b32.into()`
+   |            ^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |     id_u64(b32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:203:12
@@ -484,25 +524,29 @@ LL |     id_u64(bsize);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     id_u64(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:207:14
    |
 LL |     id_usize(b8);
-   |              ^^
-   |              |
-   |              expected `usize`, found `u8`
-   |              help: you can convert a `u8` to a `usize`: `b8.into()`
+   |              ^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |     id_usize(b8.into());
+   |                +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:210:14
    |
 LL |     id_usize(b16);
-   |              ^^^
-   |              |
-   |              expected `usize`, found `u16`
-   |              help: you can convert a `u16` to a `usize`: `b16.into()`
+   |              ^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |     id_usize(b16.into());
+   |                 +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:213:14
@@ -513,7 +557,7 @@ LL |     id_usize(b32);
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     id_usize(b32.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:216:14
@@ -524,7 +568,7 @@ LL |     id_usize(b64);
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     id_usize(b64.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error: aborting due to 52 previous errors
 
diff --git a/src/test/ui/issue-72470-llvm-dominate.rs b/src/test/ui/issue-72470-llvm-dominate.rs
deleted file mode 100644 (file)
index 5bb69a0..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// compile-flags: -C opt-level=3
-// aux-build: issue-72470-lib.rs
-// edition:2018
-// build-pass
-
-// Regression test for issue #72470, using the minimization
-// in https://github.com/jonas-schievink/llvm-error
-
-extern crate issue_72470_lib;
-
-use std::future::Future;
-use std::pin::Pin;
-use std::sync::Mutex;
-use std::task::Poll::{Pending, Ready};
-
-#[allow(dead_code)]
-enum Msg {
-    A(Vec<()>),
-    B,
-}
-
-#[allow(dead_code)]
-enum Out {
-    _0(Option<Msg>),
-    Disabled,
-}
-
-#[allow(unused_must_use)]
-fn main() {
-    let mut rx = issue_72470_lib::unbounded_channel::<Msg>();
-    let entity = Mutex::new(());
-    issue_72470_lib::run(async move {
-        {
-            let output = {
-                let mut fut = rx.recv();
-                issue_72470_lib::poll_fn(|cx| {
-                    loop {
-                        let fut = unsafe { Pin::new_unchecked(&mut fut) };
-                        let out = match fut.poll(cx) {
-                            Ready(out) => out,
-                            Pending => {
-                                break;
-                            }
-                        };
-                        #[allow(unused_variables)]
-                        match &out {
-                            Some(_msg) => {}
-                            _ => break,
-                        }
-                        return Ready(Out::_0(out));
-                    }
-                    Ready(Out::_0(None))
-                })
-                .await
-            };
-            match output {
-                Out::_0(Some(_msg)) => {
-                    entity.lock();
-                }
-                Out::_0(None) => unreachable!(),
-                _ => unreachable!(),
-            }
-        }
-        entity.lock();
-    });
-}
index 0796ede52a9ee5667e269d64a76291ca98f3c115..075c92e65de820cb4c42e713e45ada488e7e7897 100644 (file)
@@ -7,7 +7,7 @@ LL |     foo(1*(1 as isize));
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo((1*(1 as isize)).try_into().unwrap());
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         +              +++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/issue-13359.rs:10:9
@@ -18,7 +18,7 @@ LL |     bar(1*(1 as usize));
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     bar((1*(1 as usize)).try_into().unwrap());
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         +              +++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
index a925fc29c8cf02ed494469e525693b105ba31937..babbb6e519bc0674069d6fd63a4c06c43bed5db7 100644 (file)
@@ -9,7 +9,7 @@ LL |   let x: u32 = 20i32;
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |   let x: u32 = 20u32;
-   |                ~~~~~
+   |                  ~~~
 
 error: aborting due to previous error
 
index 6bf76c4904dcbb6db4791d56bfc5e7591d5dfc85..da44566d075c4c5530a9414189ea8e2cea537e2c 100644 (file)
@@ -7,7 +7,7 @@ LL |     println!("{}", foo(10i32));
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     println!("{}", foo(10u32));
-   |                        ~~~~~
+   |                          ~~~
 
 error: aborting due to previous error
 
index 08f352c11fa12cce2dc6069f9d59749b8e89a87b..7629a5a3be1ea475a59ff154d41fecfb8f7669f6 100644 (file)
@@ -4,5 +4,4 @@
 fn main() {
     (|| Box::new(*(&[0][..])))();
     //~^ ERROR the size for values of type
-    //~| ERROR the size for values of type
 }
index ee1464fd8481105f4f87e2969c2dc80aaccaf7b2..214477f6c60ef4881258e7fa883a53453acb06f9 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi
   --> $DIR/issue-17651.rs:5:18
    |
 LL |     (|| Box::new(*(&[0][..])))();
-   |                  ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         -------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by `Box::<T>::new`
@@ -11,16 +13,6 @@ note: required by `Box::<T>::new`
 LL |     pub fn new(x: T) -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
-  --> $DIR/issue-17651.rs:5:9
-   |
-LL |     (|| Box::new(*(&[0][..])))();
-   |         ^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[{integer}]`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
index 2a5416ce85ba65e78140c4a40aaa85dce68c7338..b9e27873636c3302c567ca2d8b9037d59ab4cf5d 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn foo(b: &dyn Bar) {
    |            ^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-18959.rs:1:20
    |
@@ -12,6 +11,7 @@ LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
    |                    ^^^ ...because method `foo` has generic type parameters
 LL | pub trait Bar: Foo { }
    |           --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
index f66e0a1c07841b6f80ce0767e251abd6a9f42ff2..3970a4155e95c2ec53f4c110a0f347520bc48aed 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 trait Trait { fn dummy(&self) { } }
 
 #[derive(Debug)]
index 555d0ff0dc787c71f92fce52d3dea6df749bf055..7b37e1f95dcc654da9b864e543b211b3c480a990 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     let test: &mut dyn Bar = &mut thing;
    |               ^^^^^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19538.rs:2:8
    |
@@ -13,6 +12,7 @@ LL |     fn foo<T>(&self, val: T);
 ...
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:30
@@ -20,7 +20,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     let test: &mut dyn Bar = &mut thing;
    |                              ^^^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19538.rs:2:8
    |
@@ -29,6 +28,7 @@ LL |     fn foo<T>(&self, val: T);
 ...
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
    = note: required by cast to type `&mut dyn Bar`
 
diff --git a/src/test/ui/issues/issue-19883.rs b/src/test/ui/issues/issue-19883.rs
deleted file mode 100644 (file)
index 5cf4220..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-trait From<Src> {
-    type Output;
-
-    fn from(src: Src) -> <Self as From<Src>>::Output;
-}
-
-trait To: Sized {
-    fn to<Dst: From<Self>>(self) ->
-        <Dst as From<Self>>::Dst
-        //~^ ERROR cannot find associated type `Dst` in trait `From`
-    {
-        From::from(self)
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-19883.stderr b/src/test/ui/issues/issue-19883.stderr
deleted file mode 100644 (file)
index bd6a86b..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0576]: cannot find associated type `Dst` in trait `From`
-  --> $DIR/issue-19883.rs:9:30
-   |
-LL |     type Output;
-   |     ------------ associated type `Output` defined here
-...
-LL |         <Dst as From<Self>>::Dst
-   |                              ^^^
-   |                              |
-   |                              not found in `From`
-   |                              help: maybe you meant this associated type: `Output`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0576`.
index 25a90df45613b9b8e2777a9965c2b1b90c46f045..ce3ab6b599864ded9ba9cf5b66316137b0af37da 100644 (file)
@@ -2,9 +2,12 @@ error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cann
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ doesn't have a size known at compile-time
+   |                 ^^^^^^^
+   |                 |
+   |                 expected an implementor of trait `IntoIterator`
+   |                 help: consider mutably borrowing here: `&mut *things`
    |
-   = help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+   = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
    = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
 note: required by `into_iter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
diff --git a/src/test/ui/issues/issue-20692.rs b/src/test/ui/issues/issue-20692.rs
deleted file mode 100644 (file)
index 1cb2d8c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-trait Array: Sized + Copy {}
-
-fn f<T: Array>(x: &T) {
-    let _ = x
-    //~^ ERROR `Array` cannot be made into an object
-    as
-    &dyn Array;
-    //~^ ERROR `Array` cannot be made into an object
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr
deleted file mode 100644 (file)
index 1d7f252..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0038]: the trait `Array` cannot be made into an object
-  --> $DIR/issue-20692.rs:7:5
-   |
-LL |     &dyn Array;
-   |     ^^^^^^^^^^ `Array` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-20692.rs:1:14
-   |
-LL | trait Array: Sized + Copy {}
-   |       -----  ^^^^^   ^^^^ ...because it requires `Self: Sized`
-   |       |      |
-   |       |      ...because it requires `Self: Sized`
-   |       this trait cannot be made into an object...
-
-error[E0038]: the trait `Array` cannot be made into an object
-  --> $DIR/issue-20692.rs:4:13
-   |
-LL |     let _ = x
-   |             ^ `Array` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-20692.rs:1:14
-   |
-LL | trait Array: Sized + Copy {}
-   |       -----  ^^^^^   ^^^^ ...because it requires `Self: Sized`
-   |       |      |
-   |       |      ...because it requires `Self: Sized`
-   |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Array>` for `&T`
-   = note: required by cast to type `&dyn Array`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/issues/issue-21363.rs b/src/test/ui/issues/issue-21363.rs
deleted file mode 100644 (file)
index acc28cb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// check-pass
-// pretty-expanded FIXME #23616
-
-#![no_implicit_prelude]
-
-trait Iterator {
-    type Item;
-    fn dummy(&self) { }
-}
-
-impl<'a, T> Iterator for &'a mut (dyn Iterator<Item=T> + 'a) {
-    type Item = T;
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-23825.rs b/src/test/ui/issues/issue-23825.rs
deleted file mode 100644 (file)
index a9f0095..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-trait Stringify {
-    fn to_string(&self) -> String;
-}
-
-impl Stringify for u32 {
-    fn to_string(&self) -> String { format!("u32: {}", *self) }
-}
-
-impl Stringify for f32 {
-    fn to_string(&self) -> String { format!("f32: {}", *self) }
-}
-
-fn print<T: Stringify>(x: T) -> String {
-    x.to_string()
-}
-
-fn main() {
-    assert_eq!(&print(5), "u32: 5");
-    assert_eq!(&print(5.0), "f32: 5");
-}
diff --git a/src/test/ui/issues/issue-23833.rs b/src/test/ui/issues/issue-23833.rs
deleted file mode 100644 (file)
index d4128fa..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-#![allow(unused_imports)]
-use std::fmt;
-
-const A_I8_T
-    : [u32; (i8::MAX as i8 - 1i8) as usize]
-    = [0; (i8::MAX as usize) - 1];
-
-fn main() {
-    foo(&A_I8_T[..]);
-}
-
-fn foo<T:fmt::Debug>(x: T) {
-    println!("{:?}", x);
-}
index fff9b3c303a637d8071659f4dd7f8a0893b14d9c..9c87ee6104a0d27e25f56b3cd47020ca8ccabee1 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnMut<(_, char)>` closure, found `()`
   --> $DIR/issue-23966.rs:2:32
    |
 LL |     "".chars().fold(|_, _| (), ());
-   |                                ^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |                ----            ^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |                |
+   |                required by a bound introduced by this call
    |
    = help: the trait `FnMut<(_, char)>` is not implemented for `()`
 
index ece99596e58f406844ac5846434548c804d09f0d..159cc484c5d4f35c196f66a874c4592d91a31ce1 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): InOut<_>` is not satisfied
   --> $DIR/issue-25076.rs:10:20
    |
 LL |     do_fold(bot(), ());
-   |                    ^^ the trait `InOut<_>` is not implemented for `()`
+   |     -------        ^^ the trait `InOut<_>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `do_fold`
   --> $DIR/issue-25076.rs:5:18
index 70caeb0ea39092578f8c7d32a234dfd8504f645f..6a74f4ed489a16828f1224aa340f28d24610bd0c 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:2:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -29,7 +31,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:9:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -50,7 +54,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:18:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -63,7 +69,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:22:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
index 79f5db650d9dcb76e89b0917aeae621e0e6a45bf..71bbdf5dec7696600f3a02ee2544624d0c097244 100644 (file)
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-30355.rs:5:6
+  --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |      ^ doesn't have a size known at compile-time
+   |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: all function arguments must have a statically known size
diff --git a/src/test/ui/issues/issue-33498.rs b/src/test/ui/issues/issue-33498.rs
deleted file mode 100644 (file)
index 9c8a97e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-#![allow(unused_variables)]
-pub fn main() {
-    let x = (0, 2);
-
-    match x {
-        (0, ref y) => {}
-        (y, 0) => {}
-        _ => (),
-    }
-}
diff --git a/src/test/ui/issues/issue-34194.rs b/src/test/ui/issues/issue-34194.rs
deleted file mode 100644 (file)
index 6dce556..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-pass
-#![allow(dead_code)]
-
-struct A {
-    a: &'static (),
-}
-
-static B: &'static A = &A { a: &() };
-static C: &'static A = &B;
-
-fn main() {}
index b1071934bb2f3cea0aeb98e1833e4412da85f23e..c70cd8b5077a924fa9ef52a5f988d7a31ff0b1ef 100644 (file)
@@ -6,5 +6,5 @@ enum Test {
 
 fn main() {
     Test::Drill(field: 42);
-    //~^ ERROR expected type, found
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
 }
index c8bad3b3bb502bbda95299b31c68c6e06dea2d10..fbff75e37d9f0864ff0630fbf99acbe6b6f058dd 100644 (file)
@@ -1,13 +1,18 @@
-error: expected type, found `42`
-  --> $DIR/issue-34255-1.rs:8:24
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-34255-1.rs:8:5
    |
 LL |     Test::Drill(field: 42);
-   |                      - ^^ expected type
-   |                      |
-   |                      tried to parse a type due to this type ascription
+   |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Test::Drill` is a struct, use braces as delimiters
+   |
+LL |     Test::Drill { field: 42 };
+   |                 ~           ~
+help: if `Test::Drill` is a function, use the arguments directly
+   |
+LL -     Test::Drill(field: 42);
+LL +     Test::Drill(42);
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-34784.rs b/src/test/ui/issues/issue-34784.rs
deleted file mode 100644 (file)
index 98d9434..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// run-pass
-
-#![warn(pointer_structural_match)]
-#![allow(dead_code)]
-const C: *const u8 = &0;
-
-fn foo(x: *const u8) {
-    match x {
-        C => {}
-        _ => {}
-    }
-}
-
-const D: *const [u8; 4] = b"abcd";
-
-fn main() {
-    match D {
-        D => {}
-        _ => {}
-    }
-}
diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs
deleted file mode 100644 (file)
index cc35213..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// check-pass
-#![feature(specialization)]
-//~^ WARN the feature `specialization` is incomplete
-
-fn main() {}
-
-pub trait Alpha<T> { }
-
-pub trait Beta {
-    type Event;
-}
-
-pub trait Delta {
-    type Handle;
-    fn process(&self);
-}
-
-pub struct Parent<A, T>(A, T);
-
-impl<A, T> Delta for Parent<A, T>
-where A: Alpha<T::Handle>,
-      T: Delta,
-      T::Handle: Beta<Event = <Handle as Beta>::Event> {
-    type Handle = Handle;
-    default fn process(&self) {
-        unimplemented!()
-    }
-}
-
-impl<A, T> Delta for Parent<A, T>
-where A: Alpha<T::Handle> + Alpha<Handle>,
-      T: Delta,
-      T::Handle: Beta<Event = <Handle as Beta>::Event> {
-      fn process(&self) {
-        unimplemented!()
-      }
-}
-
-pub struct Handle;
-
-impl Beta for Handle {
-    type Event = ();
-}
diff --git a/src/test/ui/issues/issue-35376.stderr b/src/test/ui/issues/issue-35376.stderr
deleted file mode 100644 (file)
index 835277d..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-35376.rs:2: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
-
-warning: 1 warning emitted
-
diff --git a/src/test/ui/issues/issue-36768.rs b/src/test/ui/issues/issue-36768.rs
deleted file mode 100644 (file)
index f671cbc..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// run-pass
-// compile-flags:--test
-#![deny(private_in_public)]
-
-#[test] fn foo() {}
-mod foo {}
-
-#[test] fn core() {}
-extern crate core;
diff --git a/src/test/ui/issues/issue-37433.rs b/src/test/ui/issues/issue-37433.rs
deleted file mode 100644 (file)
index 1c362e8..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// build-fail
-// ignore-emscripten no llvm_asm! support
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-fn main() {
-    unsafe {
-        llvm_asm!("" :: "r"(""));
-        //~^ ERROR: invalid value for constraint in inline assembly
-    }
-}
diff --git a/src/test/ui/issues/issue-37433.stderr b/src/test/ui/issues/issue-37433.stderr
deleted file mode 100644 (file)
index 44a8eb3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/issue-37433.rs:9:29
-   |
-LL |         llvm_asm!("" :: "r"(""));
-   |                             ^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0669`.
index 408d8d866d862efdfb7989f471d0be0e00aa6dfb..1809e822c54213d4dbdc222bbac07f17d90fbf4b 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 trait T {
     fn print(&self);
diff --git a/src/test/ui/issues/issue-38002.rs b/src/test/ui/issues/issue-38002.rs
deleted file mode 100644 (file)
index fdb31fc..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-// Check that constant ADTs are codegened OK, part k of N.
-
-enum Bar {
-    C
-}
-
-enum Foo {
-    A {},
-    B {
-        y: usize,
-        z: Bar
-    },
-}
-
-const LIST: [(usize, Foo); 2] = [
-    (51, Foo::B { y: 42, z: Bar::C }),
-    (52, Foo::B { y: 45, z: Bar::C }),
-];
-
-pub fn main() {
-    match LIST {
-        [
-            (51, Foo::B { y: 42, z: Bar::C }),
-            (52, Foo::B { y: 45, z: Bar::C })
-        ] => {}
-        _ => {
-            // I would want to print the enum here, but if
-            // the discriminant is garbage this causes an
-            // `unreachable` and silent process exit.
-            panic!("trivial match failed")
-        }
-    }
-}
diff --git a/src/test/ui/issues/issue-3935.rs b/src/test/ui/issues/issue-3935.rs
deleted file mode 100644 (file)
index e98d68e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-pass
-
-#[derive(PartialEq)]
-struct Bike {
-    name: String,
-}
-
-pub fn main() {
-    let town_bike = Bike { name: "schwinn".to_string() };
-    let my_bike = Bike { name: "surly".to_string() };
-
-    assert!(town_bike != my_bike);
-}
diff --git a/src/test/ui/issues/issue-41255.rs b/src/test/ui/issues/issue-41255.rs
deleted file mode 100644 (file)
index 9d7072f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Matching against float literals should result in a linter error
-
-#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
-#![allow(unused)]
-#![forbid(illegal_floating_point_literal_pattern)]
-
-fn main() {
-    let x = 42.0;
-    match x {
-        5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                   //~| WARNING hard error
-        5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
-                      //~| WARNING hard error
-        -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                    //~| WARNING hard error
-        1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                           //~| WARNING hard error
-                           //~| ERROR floating-point types cannot be used in patterns
-                           //~| WARNING hard error
-        39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
-                             //~| ERROR floating-point types cannot be used in patterns
-                             //~| WARNING hard error
-                             //~| WARNING hard error
-
-        ..71.0 => {}
-        //~^ ERROR floating-point types cannot be used in patterns
-        //~| WARNING this was previously accepted by the compiler
-        ..=72.0 => {}
-        //~^ ERROR floating-point types cannot be used in patterns
-        //~| WARNING this was previously accepted by the compiler
-        71.0.. => {}
-        //~^ ERROR floating-point types cannot be used in patterns
-        //~| WARNING this was previously accepted by the compiler
-        _ => {},
-    };
-    let y = 5.0;
-    // Same for tuples
-    match (x, 5) {
-        (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
-                         //~| WARNING hard error
-        _ => {},
-    }
-    // Or structs
-    struct Foo { x: f32 };
-    match (Foo { x }) {
-        Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
-                              //~| WARNING hard error
-        _ => {},
-    }
-}
diff --git a/src/test/ui/issues/issue-41255.stderr b/src/test/ui/issues/issue-41255.stderr
deleted file mode 100644 (file)
index bf81c8d..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:11:9
-   |
-LL |         5.0 => {},
-   |         ^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-41255.rs:6:11
-   |
-LL | #![forbid(illegal_floating_point_literal_pattern)]
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:13:9
-   |
-LL |         5.0f32 => {},
-   |         ^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:15:10
-   |
-LL |         -5.0 => {},
-   |          ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:17:9
-   |
-LL |         1.0 .. 33.0 => {},
-   |         ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:17:16
-   |
-LL |         1.0 .. 33.0 => {},
-   |                ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:21:9
-   |
-LL |         39.0 ..= 70.0 => {},
-   |         ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:21:18
-   |
-LL |         39.0 ..= 70.0 => {},
-   |                  ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:26:11
-   |
-LL |         ..71.0 => {}
-   |           ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:29:12
-   |
-LL |         ..=72.0 => {}
-   |            ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:32:9
-   |
-LL |         71.0.. => {}
-   |         ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:40:10
-   |
-LL |         (3.14, 1) => {},
-   |          ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
-  --> $DIR/issue-41255.rs:47:18
-   |
-LL |         Foo { x: 2.0 } => {},
-   |                  ^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 12 previous errors
-
diff --git a/src/test/ui/issues/issue-42944.rs b/src/test/ui/issues/issue-42944.rs
deleted file mode 100644 (file)
index a440485..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-mod foo {
-    pub struct Bx(());
-}
-
-mod bar {
-    use foo::Bx;
-
-    fn foo() {
-        Bx(());
-        //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
-    }
-}
-
-mod baz {
-    fn foo() {
-        Bx(());
-        //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425]
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-42944.stderr b/src/test/ui/issues/issue-42944.stderr
deleted file mode 100644 (file)
index 0084925..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-error[E0423]: cannot initialize a tuple struct which contains private fields
-  --> $DIR/issue-42944.rs:9:9
-   |
-LL |         Bx(());
-   |         ^^
-   |
-note: constructor is not visible here due to private fields
-  --> $DIR/issue-42944.rs:2:19
-   |
-LL |     pub struct Bx(());
-   |                   ^^ private field
-
-error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
-  --> $DIR/issue-42944.rs:16:9
-   |
-LL |         Bx(());
-   |         ^^ not found in this scope
-   |
-help: consider importing this tuple struct
-   |
-LL |     use foo::Bx;
-   |
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0423, E0425.
-For more information about an error, try `rustc --explain E0423`.
index f187969ff4e86ad8595211ebf3e121b28b02f630..fa3b58e1279378353ddd0c6033eb9edee9518b0f 100644 (file)
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `*v`, as `v` is a captured variable in an `FnMu
 LL | fn f<'r, T>(v: &'r T) -> Box<dyn FnMut() -> T + 'r> {
    |             - captured outer variable
 LL |     id(Box::new(|| *v))
-   |                    ^^ move occurs because `*v` has type `T`, which does not implement the `Copy` trait
+   |                 ---^^
+   |                 |  |
+   |                 |  move occurs because `*v` has type `T`, which does not implement the `Copy` trait
+   |                 captured by this `FnMut` closure
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr
deleted file mode 100644 (file)
index 9e9cbcf..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-LL |         let f = |v: &mut Vec<_>| {
-LL |             unsafe {
-   |             ^^^^^^ unnecessary `unsafe` block
-   |
-note: the lint level is defined here
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
-   |
-LL | #[deny(unused_unsafe)]
-   |        ^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-...
-LL |                 |w: &mut Vec<u32>| { unsafe {
-   |                                      ^^^^^^ unnecessary `unsafe` block
-
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-...
-LL |             |x: &mut Vec<u32>| { unsafe {
-   |                                  ^^^^^^ unnecessary `unsafe` block
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs
deleted file mode 100644 (file)
index ac1cfd6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// revisions: mir thir
-// [thir]compile-flags: -Zthir-unsafeck
-
-#[deny(unused_unsafe)]
-fn main() {
-    let mut v = Vec::<i32>::with_capacity(24);
-
-    unsafe {
-        let f = |v: &mut Vec<_>| {
-            unsafe { //~ ERROR unnecessary `unsafe`
-                v.set_len(24);
-                |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
-                    w.set_len(32);
-                } };
-            }
-            |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
-                x.set_len(40);
-            } };
-        };
-
-        v.set_len(0);
-        f(&mut v);
-    }
-
-    |y: &mut Vec<u32>| { unsafe {
-        y.set_len(48);
-    } };
-}
diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr
deleted file mode 100644 (file)
index 9e9cbcf..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-LL |         let f = |v: &mut Vec<_>| {
-LL |             unsafe {
-   |             ^^^^^^ unnecessary `unsafe` block
-   |
-note: the lint level is defined here
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
-   |
-LL | #[deny(unused_unsafe)]
-   |        ^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-...
-LL |                 |w: &mut Vec<u32>| { unsafe {
-   |                                      ^^^^^^ unnecessary `unsafe` block
-
-error: unnecessary `unsafe` block
-  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
-   |
-LL |     unsafe {
-   |     ------ because it's nested under this `unsafe` block
-...
-LL |             |x: &mut Vec<u32>| { unsafe {
-   |                                  ^^^^^^ unnecessary `unsafe` block
-
-error: aborting due to 3 previous errors
-
index 8a6a199148c39c0848c491e93f86df20bdd94bb6..2e542644b70d4db676b8ab44bef27bf45efd0ca9 100644 (file)
@@ -4,7 +4,9 @@ error[E0593]: function is expected to take a single 0-tuple as argument, but it
 LL |     fn f(&self, _: ()) {
    |     ------------------ takes 2 distinct arguments
 LL |         None::<()>.map(Self::f);
-   |                        ^^^^^^^ expected function that takes a single 0-tuple as argument
+   |                    --- ^^^^^^^ expected function that takes a single 0-tuple as argument
+   |                    |
+   |                    required by a bound introduced by this call
 
 error: aborting due to previous error
 
index d9680a26e09c7446ba68c4dc67870f37ec17f385..acf7626c634e3c3100c82ee00e31d8e35701dc26 100644 (file)
@@ -5,7 +5,9 @@ LL |     pub fn new(foo: Option<i32>, _: ()) -> Foo {
    |     ------------------------------------------ takes 2 arguments
 ...
 LL |         self.foo.map(Foo::new)
-   |                      ^^^^^^^^ expected function that takes 1 argument
+   |                  --- ^^^^^^^^ expected function that takes 1 argument
+   |                  |
+   |                  required by a bound introduced by this call
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:9
@@ -14,7 +16,9 @@ LL |     Bar(i32),
    |     -------- takes 1 argument
 ...
 LL |     foo(Qux::Bar);
-   |         ^^^^^^^^ expected function that takes 0 arguments
+   |     --- ^^^^^^^^ expected function that takes 0 arguments
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-47706.rs:22:8
index eb9eb680200672da966418f7491ce6a5b9a64422..09c52292dccaff9ba05d44d83dd16faf69881588 100644 (file)
@@ -2,7 +2,10 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state`
   --> $DIR/issue-51102.rs:13:17
    |
 LL |                 state: 0,
-   |                 ^^^^^ struct `SimpleStruct` does not have this field
+   |                 ^^^^^
+   |                 |
+   |                 struct `SimpleStruct` does not have this field
+   |                 help: `SimpleStruct` has a field named `no_state_here`
 
 error[E0025]: field `no_state_here` bound multiple times in the pattern
   --> $DIR/issue-51102.rs:24:17
index bb74f0e0dc3c79bb3be14528954f84d36370c54c..35402dff675534f769bfe47a343d58b254ce7fb1 100644 (file)
@@ -6,7 +6,7 @@ fn missing_discourses() -> Result<isize, ()> {
 
 fn forbidden_narratives() -> Result<isize, ()> {
     missing_discourses()?
-    //~^ ERROR try expression alternatives have incompatible types
+    //~^ ERROR: `?` operator has incompatible types
 }
 
 fn main() {}
index 2c821aa23088d6d675b598da2a2cf6a787ae2611..0f61e03c3b58fb522d4d34d44407b74703719a54 100644 (file)
@@ -1,9 +1,10 @@
-error[E0308]: try expression alternatives have incompatible types
+error[E0308]: `?` operator has incompatible types
   --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
    |
 LL |     missing_discourses()?
    |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
    |
+   = note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
    = note: expected enum `Result<isize, ()>`
               found type `isize`
 help: try removing this `?`
diff --git a/src/test/ui/issues/issue-53912.rs b/src/test/ui/issues/issue-53912.rs
deleted file mode 100644 (file)
index 65b6825..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-
-// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
-// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
-// symbol mangling fix produces the correct result.
-
-fn dummy() {}
-
-mod llvm {
-    pub(crate) struct Foo;
-}
-mod foo {
-    pub(crate) struct Foo<T>(T);
-
-    impl Foo<::llvm::Foo> {
-        pub(crate) fn foo() {
-            for _ in 0..0 {
-                for _ in &[::dummy()] {
-                    ::dummy();
-                    ::dummy();
-                    ::dummy();
-                }
-            }
-        }
-    }
-
-    pub(crate) fn foo() {
-        Foo::foo();
-        Foo::foo();
-    }
-}
-
-pub fn foo() {
-    foo::foo();
-}
-
-fn main() {}
index ffe3bb737ad6a2f8afc28e97e8f774e645c04467..952159ffc3bfe6f762c142210555ae4379ad82b9 100644 (file)
@@ -15,7 +15,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/issue-55796.rs:18:9
    |
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
@@ -40,7 +40,7 @@ note: ...so that the type `Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/iss
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/issue-55796.rs:23:9
    |
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
index 3d7acee0a56eb9fbd3cf83c93ff43a3c179319bc..7ee5bc6ec617470f0acefbc8a9724bad42e47088 100644 (file)
@@ -3,6 +3,16 @@ error: missing trait in a trait impl
    |
 LL | impl for T {}
    |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for T {}
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for T {}
+LL + impl T {}
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-56685.rs b/src/test/ui/issues/issue-56685.rs
deleted file mode 100644 (file)
index f320c99..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#![allow(dead_code)]
-#![deny(unused_variables)]
-
-// This test aims to check that unused variable suggestions update bindings in all
-// match arms.
-
-fn main() {
-    enum E {
-        A(i32,),
-        B(i32,),
-    }
-
-    match E::A(1) {
-        E::A(x) | E::B(x) => {}
-        //~^ ERROR unused variable: `x`
-    }
-
-    enum F {
-        A(i32, i32,),
-        B(i32, i32,),
-        C(i32, i32,),
-    }
-
-    let _ = match F::A(1, 2) {
-        F::A(x, y) | F::B(x, y) => { y },
-        //~^ ERROR unused variable: `x`
-        F::C(a, b) => { 3 }
-        //~^ ERROR unused variable: `a`
-        //~^^ ERROR unused variable: `b`
-    };
-
-    let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
-    //~^ ERROR unused variable: `x`
-        y
-    } else {
-        3
-    };
-
-    while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
-    //~^ ERROR unused variable: `x`
-        let _ = y;
-        break;
-    }
-}
diff --git a/src/test/ui/issues/issue-56685.stderr b/src/test/ui/issues/issue-56685.stderr
deleted file mode 100644 (file)
index ccf357d..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-error: unused variable: `x`
-  --> $DIR/issue-56685.rs:14:14
-   |
-LL |         E::A(x) | E::B(x) => {}
-   |              ^         ^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-56685.rs:2:9
-   |
-LL | #![deny(unused_variables)]
-   |         ^^^^^^^^^^^^^^^^
-help: if this is intentional, prefix it with an underscore
-   |
-LL |         E::A(_x) | E::B(_x) => {}
-   |              ~~         ~~
-
-error: unused variable: `x`
-  --> $DIR/issue-56685.rs:25:14
-   |
-LL |         F::A(x, y) | F::B(x, y) => { y },
-   |              ^            ^
-   |
-help: if this is intentional, prefix it with an underscore
-   |
-LL |         F::A(_x, y) | F::B(_x, y) => { y },
-   |              ~~            ~~
-
-error: unused variable: `a`
-  --> $DIR/issue-56685.rs:27:14
-   |
-LL |         F::C(a, b) => { 3 }
-   |              ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
-  --> $DIR/issue-56685.rs:27:17
-   |
-LL |         F::C(a, b) => { 3 }
-   |                 ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `x`
-  --> $DIR/issue-56685.rs:32:25
-   |
-LL |     let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
-   |                         ^            ^
-   |
-help: if this is intentional, prefix it with an underscore
-   |
-LL |     let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
-   |                         ~~            ~~
-
-error: unused variable: `x`
-  --> $DIR/issue-56685.rs:39:20
-   |
-LL |     while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
-   |                    ^            ^
-   |
-help: if this is intentional, prefix it with an underscore
-   |
-LL |     while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
-   |                    ~~            ~~
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/issues/issue-57410.rs b/src/test/ui/issues/issue-57410.rs
deleted file mode 100644 (file)
index 0cf4b80..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// check-pass
-
-// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
-
-#![deny(unreachable_pub)]
-
-mod m {
-    mod imp {
-        pub fn f() {}
-    }
-
-    pub use self::imp::f;
-}
-
-pub use self::m::f;
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-5791.rs b/src/test/ui/issues/issue-5791.rs
deleted file mode 100644 (file)
index 3544160..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-#![allow(dead_code)]
-#![warn(clashing_extern_declarations)]
-// pretty-expanded FIXME #23616
-
-extern "C" {
-    #[link_name = "malloc"]
-    fn malloc1(len: i32) -> *const u8;
-    #[link_name = "malloc"]
-    //~^ WARN `malloc2` redeclares `malloc` with a different signature
-    fn malloc2(len: i32, foo: i32) -> *const u8;
-}
-
-pub fn main() {}
diff --git a/src/test/ui/issues/issue-5791.stderr b/src/test/ui/issues/issue-5791.stderr
deleted file mode 100644 (file)
index cf60e60..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: `malloc2` redeclares `malloc` with a different signature
-  --> $DIR/issue-5791.rs:9:5
-   |
-LL | /     #[link_name = "malloc"]
-LL | |     fn malloc1(len: i32) -> *const u8;
-   | |______________________________________- `malloc` previously declared here
-LL | /     #[link_name = "malloc"]
-LL | |
-LL | |     fn malloc2(len: i32, foo: i32) -> *const u8;
-   | |________________________________________________^ this signature doesn't match the previous declaration
-   |
-note: the lint level is defined here
-  --> $DIR/issue-5791.rs:3:9
-   |
-LL | #![warn(clashing_extern_declarations)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `unsafe extern "C" fn(i32) -> *const u8`
-              found `unsafe extern "C" fn(i32, i32) -> *const u8`
-
-warning: 1 warning emitted
-
index 90af47dfa79112c1dac825ed54967253d6262bc7..9b7fe1ef786f07721f557f1337f72e75b26348e2 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
   --> $DIR/issue-59494.rs:21:22
    |
 LL |     let t8 = t8n(t7, t7p(f, g));
-   |                      ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+   |              ---     ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+   |              |
+   |              required by a bound introduced by this call
    |
    = help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>`
 note: required by a bound in `t8n`
index ac33cfd0402434095b36ca5b0fe27cd968077e5c..870b25014471d9402ef178545ca6d29e8747281d 100644 (file)
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `&u32: Foo` is not satisfied
-  --> $DIR/issue-60218.rs:18:5
+  --> $DIR/issue-60218.rs:18:27
    |
 LL |     trigger_error(vec![], |x: &u32| x)
-   |     ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     -------------         ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `trigger_error`
   --> $DIR/issue-60218.rs:13:72
index 2ee55105214586f991aafdb714c9999376d86140..34893cd8f19d908ffcc7f8b93750145dc5bda854 100644 (file)
@@ -2,10 +2,11 @@ error[E0631]: type mismatch in function arguments
   --> $DIR/issue-60283.rs:17:13
    |
 LL |     foo((), drop)
-   |             ^^^^
-   |             |
-   |             expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
-   |             found signature of `fn(()) -> _`
+   |     ---     ^^^^
+   |     |       |
+   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |     |       found signature of `fn(()) -> _`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-60283.rs:12:16
@@ -20,7 +21,9 @@ error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be kn
   --> $DIR/issue-60283.rs:17:13
    |
 LL |     foo((), drop)
-   |             ^^^^ doesn't have a size known at compile-time
+   |     ---     ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
 note: required by a bound in `std::mem::drop`
index 03a65540ced04a549eba45fb8917f849868a3a53..0b8e134c9662e8f8ef7c1a7c2db749ed0e3cc45d 100644 (file)
@@ -5,7 +5,7 @@ LL |         Self(&x);
    |              ^^
    |              |
    |              borrowed value does not live long enough
-   |              requires that `x` is borrowed for `'static`
+   |              this usage requires that `x` is borrowed for `'static`
 LL |
 LL |     }
    |     - `x` dropped here while still borrowed
index 59a521c7360faaefb8e8ab376e301e9b12c69756..282e236d3d021d84217a3ee3195f2df31e70efc0 100644 (file)
@@ -8,7 +8,9 @@ error[E0277]: the trait bound `(): _Func<_>` is not satisfied
   --> $DIR/issue-66353.rs:12:41
    |
 LL |     _Func::< <() as _A>::AssocT >::func(());
-   |                                         ^^ the trait `_Func<_>` is not implemented for `()`
+   |     ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `_Func::func`
   --> $DIR/issue-66353.rs:4:5
diff --git a/src/test/ui/issues/issue-74614.rs b/src/test/ui/issues/issue-74614.rs
deleted file mode 100644 (file)
index 8b0c00b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// compile-flags:-Zpolymorphize=on
-// build-pass
-
-fn test<T>() {
-    std::mem::size_of::<T>();
-}
-
-pub fn foo<T>(_: T) -> &'static fn() {
-    &(test::<T> as fn())
-}
-
-fn outer<T>() {
-    foo(|| ());
-}
-
-fn main() {
-    outer::<u8>();
-}
index 16249a33c2fd07d78893fc8dfe3649b420925867..25562f6347e672438189c2795b24241cb3e84c7c 100644 (file)
@@ -17,7 +17,7 @@ LL |     Box::new(move |_| fut)
    = note: expected `(Pin<Box<dyn Future<Output = A> + Send>>,)`
               found `(Pin<Box<(dyn Future<Output = A> + Send + 'a)>>,)`
    = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/issue-75777.rs:13:5
    |
 LL |     Box::new(move |_| fut)
diff --git a/src/test/ui/issues/issue-78720.rs b/src/test/ui/issues/issue-78720.rs
deleted file mode 100644 (file)
index 4cdb9f4..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-fn server() -> impl {
-//~^ ERROR at least one trait must be specified
-    ().map2(|| "")
-}
-
-trait FilterBase2 {
-    fn map2<F>(self, f: F) -> Map2<F> {}
-    //~^ ERROR mismatched types
-    //~^^ ERROR the size for values of type `Self` cannot be known at compilation time
-}
-
-struct Map2<Segment2> {
-    _func: F,
-    //~^ ERROR cannot find type `F` in this scope
-}
-
-impl<F> FilterBase2 for F {}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-78720.stderr b/src/test/ui/issues/issue-78720.stderr
deleted file mode 100644 (file)
index 3dd1387..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-error: at least one trait must be specified
-  --> $DIR/issue-78720.rs:1:16
-   |
-LL | fn server() -> impl {
-   |                ^^^^
-
-error[E0412]: cannot find type `F` in this scope
-  --> $DIR/issue-78720.rs:13:12
-   |
-LL |     _func: F,
-   |            ^
-   |
-  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
-   |
-LL | pub trait Fn<Args>: FnMut<Args> {
-   | ------------------------------- similarly named trait `Fn` defined here
-   |
-help: a trait with a similar name exists
-   |
-LL |     _func: Fn,
-   |            ~~
-help: you might be missing a type parameter
-   |
-LL | struct Map2<Segment2, F> {
-   |                     +++
-
-error[E0308]: mismatched types
-  --> $DIR/issue-78720.rs:7:39
-   |
-LL |     fn map2<F>(self, f: F) -> Map2<F> {}
-   |                                       ^^ expected struct `Map2`, found `()`
-   |
-   = note: expected struct `Map2<F>`
-           found unit type `()`
-
-error[E0277]: the size for values of type `Self` cannot be known at compilation time
-  --> $DIR/issue-78720.rs:7:16
-   |
-LL |     fn map2<F>(self, f: F) -> Map2<F> {}
-   |                ^^^^ doesn't have a size known at compile-time
-   |
-   = help: unsized fn params are gated as an unstable feature
-help: consider further restricting `Self`
-   |
-LL |     fn map2<F>(self, f: F) -> Map2<F> where Self: Sized {}
-   |                                       +++++++++++++++++
-help: function arguments must have a statically known size, borrowed types always have a known size
-   |
-LL |     fn map2<F>(&self, f: F) -> Map2<F> {}
-   |                +
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0277, E0308, E0412.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-79593.rs b/src/test/ui/issues/issue-79593.rs
deleted file mode 100644 (file)
index b94278b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-mod foo {
-    pub struct Pub { private: () }
-
-    pub enum Enum {
-        Variant { x: (), y: () },
-        Other
-    }
-
-    fn correct() {
-        Pub {};
-        //~^ ERROR missing field `private` in initializer of `Pub`
-        Enum::Variant { x: () };
-        //~^ ERROR missing field `y` in initializer of `Enum`
-    }
-}
-
-fn correct() {
-    foo::Pub {};
-    //~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
-}
-
-fn wrong() {
-    foo::Enum::Variant { x: () };
-    //~^ ERROR missing field `y` in initializer of `Enum`
-    foo::Enum::Variant { };
-    //~^ ERROR missing fields `x` and `y` in initializer of `Enum`
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-79593.stderr b/src/test/ui/issues/issue-79593.stderr
deleted file mode 100644 (file)
index b8c7d4f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0063]: missing field `private` in initializer of `Pub`
-  --> $DIR/issue-79593.rs:10:9
-   |
-LL |         Pub {};
-   |         ^^^ missing `private`
-
-error[E0063]: missing field `y` in initializer of `Enum`
-  --> $DIR/issue-79593.rs:12:9
-   |
-LL |         Enum::Variant { x: () };
-   |         ^^^^^^^^^^^^^ missing `y`
-
-error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
-  --> $DIR/issue-79593.rs:18:5
-   |
-LL |     foo::Pub {};
-   |     ^^^^^^^^
-
-error[E0063]: missing field `y` in initializer of `Enum`
-  --> $DIR/issue-79593.rs:23:5
-   |
-LL |     foo::Enum::Variant { x: () };
-   |     ^^^^^^^^^^^^^^^^^^ missing `y`
-
-error[E0063]: missing fields `x` and `y` in initializer of `Enum`
-  --> $DIR/issue-79593.rs:25:5
-   |
-LL |     foo::Enum::Variant { };
-   |     ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/issues/issue-79744.rs b/src/test/ui/issues/issue-79744.rs
deleted file mode 100644 (file)
index e9725a0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-fn main() {
-    let elem = 6i8;
-    let e2 = 230;
-    //~^ ERROR literal out of range for `i8`
-    //~| HELP consider using the type `u8` instead
-
-    let mut vec = Vec::new();
-
-    vec.push(e2);
-    vec.push(elem);
-
-    println!("{:?}", vec);
-}
diff --git a/src/test/ui/issues/issue-79744.stderr b/src/test/ui/issues/issue-79744.stderr
deleted file mode 100644 (file)
index 6f6dd44..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error: literal out of range for `i8`
-  --> $DIR/issue-79744.rs:3:14
-   |
-LL |     let e2 = 230;
-   |              ^^^
-   |
-   = note: `#[deny(overflowing_literals)]` on by default
-   = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127`
-   = help: consider using the type `u8` instead
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/issues/issue-86865.rs
new file mode 100644 (file)
index 0000000..01e0a20
--- /dev/null
@@ -0,0 +1,11 @@
+use std::fmt::Write;
+
+fn main() {
+    println!(b"foo");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+    let mut s = String::new();
+    write!(s, b"foo{}", "bar");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+}
diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/issues/issue-86865.stderr
new file mode 100644 (file)
index 0000000..eed7553
--- /dev/null
@@ -0,0 +1,18 @@
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:4:14
+   |
+LL |     println!(b"foo");
+   |              -^^^^^
+   |              |
+   |              help: consider removing the leading `b`
+
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:8:15
+   |
+LL |     write!(s, b"foo{}", "bar");
+   |               -^^^^^^^
+   |               |
+   |               help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
index fc9418b36b633bbe2edc829b3f39a3888a704c27..0ec5e73f39a855ced018873205deb38b447b0708 100644 (file)
@@ -20,7 +20,9 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
   --> $DIR/issue-87199.rs:18:22
    |
 LL |     ref_arg::<[i32]>(&[5]);
-   |                      ^^^^ doesn't have a size known at compile-time
+   |     ---------------- ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `ref_arg`
index 4c67dbf6796b305cdfe41b5d3342482f903aa4ae..c70093bafb69bdb4fc776e2d591e45424fe1a17c 100644 (file)
@@ -7,7 +7,7 @@ LL |     A = 1i64,
 help: change the type of the numeric literal from `i64` to `isize`
    |
 LL |     A = 1isize,
-   |         ~~~~~~
+   |          ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-8761.rs:5:9
@@ -18,7 +18,7 @@ LL |     B = 2u8
 help: change the type of the numeric literal from `u8` to `isize`
    |
 LL |     B = 2isize
-   |         ~~~~~~
+   |          ~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
deleted file mode 100644 (file)
index ecfa5c6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-trait Foo {
-    type T;
-    fn foo(&self, t: Self::T);
-//~^ NOTE expected 0 type parameters
-}
-
-impl Foo for u32 {
-    type T = ();
-
-    fn foo(&self, t: impl Clone) {}
-//~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-//~| NOTE found 1 type parameter
-//~| NOTE `impl Trait` introduces an implicit type parameter
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr b/src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
deleted file mode 100644 (file)
index 30322f8..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
-   |
-LL |     fn foo(&self, t: Self::T);
-   |           - expected 0 type parameters
-...
-LL |     fn foo(&self, t: impl Clone) {}
-   |                      ^^^^^^^^^^
-   |                      |
-   |                      found 1 type parameter
-   |                      `impl Trait` introduces an implicit type parameter
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0049`.
index 60ad68cec414393b94752330474232c6c041e23a..89975e9683dbf4eadc3456d9dffcd5504f1135bf 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-impl-type-params-2.rs:6:14
index ac43c549d8d92f8e89eb553a4d660c8d92bd2e51..016cd393c859195dd812648915ceb3ad76c14741 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
index a486ab17c888f07a0d4c4f485f73b0c948c08e5a..eaf34dff41bf0f8c083dd1b59da0a22a707846f5 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
diff --git a/src/test/ui/lifetimes/issue-77175.rs b/src/test/ui/lifetimes/issue-77175.rs
new file mode 100644 (file)
index 0000000..2282752
--- /dev/null
@@ -0,0 +1,19 @@
+#[deny(single_use_lifetimes)]
+// edition:2018
+// check-pass
+
+// Prior to the fix, the compiler complained that the 'a lifetime was only used
+// once. This was obviously wrong since the lifetime is used twice: For the s3
+// parameter and the return type. The issue was caused by the compiler
+// desugaring the async function into a generator that uses only a single
+// lifetime, which then the validator complained about becauase of the
+// single_use_lifetimes constraints.
+async fn bar<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str {
+    s3
+}
+
+fn foo<'a>(s1: String, s2: &'_ str, s3: &'a str) -> &'a str {
+    s3
+}
+
+fn main() {}
index 8c87f6da8dc3a873819236fa9eec9e0e432a2fc5..e18d725faefea722f2073e3230fb8fc935bcccf6 100644 (file)
@@ -8,6 +8,17 @@ LL |     a: &'b str,
    |
    = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
 
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
+   |
+LL | #[derive(Eq, PartialEq)]
+   |          -- lifetime `'b` is missing in item created through this procedural macro
+LL | struct Test {
+LL |     a: &'b str,
+   |         ^^ undeclared lifetime
+   |
+   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
+
 error[E0261]: use of undeclared lifetime name `'b`
   --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:13:13
    |
@@ -24,17 +35,6 @@ help: consider introducing lifetime `'b` here
 LL |     fn foo<'b>(&'b self) {}
    |           ++++
 
-error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/undeclared-lifetime-used-in-debug-macro-issue-70152.rs:3:9
-   |
-LL | #[derive(Eq, PartialEq)]
-   |          -- lifetime `'b` is missing in item created through this procedural macro
-LL | struct Test {
-LL |     a: &'b str,
-   |         ^^ undeclared lifetime
-   |
-   = help: if you want to experiment with in-band lifetime bindings, add `#![feature(in_band_lifetimes)]` to the crate attributes
-
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/lint/enable-unstable-lib-feature.rs b/src/test/ui/lint/enable-unstable-lib-feature.rs
new file mode 100644 (file)
index 0000000..aa6a973
--- /dev/null
@@ -0,0 +1,13 @@
+// Test that enabling an unstable feature disables warnings
+
+// aux-build:stability-cfg2.rs
+
+#![feature(unstable_test_feature)]
+#![deny(non_snake_case)] // To trigger a hard error
+
+// Shouldn't generate a warning about unstable features
+extern crate stability_cfg2;
+
+pub fn BOGUS() { } //~ ERROR
+
+pub fn main() { }
diff --git a/src/test/ui/lint/enable-unstable-lib-feature.stderr b/src/test/ui/lint/enable-unstable-lib-feature.stderr
new file mode 100644 (file)
index 0000000..bb4e928
--- /dev/null
@@ -0,0 +1,14 @@
+error: function `BOGUS` should have a snake case name
+  --> $DIR/enable-unstable-lib-feature.rs:11:8
+   |
+LL | pub fn BOGUS() { }
+   |        ^^^^^ help: convert the identifier to snake case: `bogus`
+   |
+note: the lint level is defined here
+  --> $DIR/enable-unstable-lib-feature.rs:6:9
+   |
+LL | #![deny(non_snake_case)] // To trigger a hard error
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/issue-57410.rs b/src/test/ui/lint/issue-57410.rs
new file mode 100644 (file)
index 0000000..0cf4b80
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::imp::f`.
+
+#![deny(unreachable_pub)]
+
+mod m {
+    mod imp {
+        pub fn f() {}
+    }
+
+    pub use self::imp::f;
+}
+
+pub use self::m::f;
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-79744.rs b/src/test/ui/lint/issue-79744.rs
new file mode 100644 (file)
index 0000000..e9725a0
--- /dev/null
@@ -0,0 +1,13 @@
+fn main() {
+    let elem = 6i8;
+    let e2 = 230;
+    //~^ ERROR literal out of range for `i8`
+    //~| HELP consider using the type `u8` instead
+
+    let mut vec = Vec::new();
+
+    vec.push(e2);
+    vec.push(elem);
+
+    println!("{:?}", vec);
+}
diff --git a/src/test/ui/lint/issue-79744.stderr b/src/test/ui/lint/issue-79744.stderr
new file mode 100644 (file)
index 0000000..6f6dd44
--- /dev/null
@@ -0,0 +1,12 @@
+error: literal out of range for `i8`
+  --> $DIR/issue-79744.rs:3:14
+   |
+LL |     let e2 = 230;
+   |              ^^^
+   |
+   = note: `#[deny(overflowing_literals)]` on by default
+   = note: the literal `230` does not fit into the type `i8` whose range is `-128..=127`
+   = help: consider using the type `u8` instead
+
+error: aborting due to previous error
+
index 9eae7da90047e5ea3e019bf98b83ef9bc80df69f..1d5f9ebb5e5c5e3ba1558e1ab559c4261e347e5b 100644 (file)
@@ -2,109 +2,210 @@ error: unnecessary parentheses around `return` value
   --> $DIR/lint-unnecessary-parens.rs:13:12
    |
 LL |     return (1);
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
    |
 note: the lint level is defined here
   --> $DIR/lint-unnecessary-parens.rs:3:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     return (1);
+LL +     return 1;
+   | 
 
 error: unnecessary parentheses around `return` value
   --> $DIR/lint-unnecessary-parens.rs:16:12
    |
 LL |     return (X { y });
-   |            ^^^^^^^^^ help: remove these parentheses
+   |            ^       ^
+   |
+help: remove these parentheses
+   |
+LL -     return (X { y });
+LL +     return X { y };
+   | 
 
 error: unnecessary parentheses around type
   --> $DIR/lint-unnecessary-parens.rs:19:46
    |
 LL | pub fn unused_parens_around_return_type() -> (u32) {
-   |                                              ^^^^^ help: remove these parentheses
+   |                                              ^   ^
+   |
+help: remove these parentheses
+   |
+LL - pub fn unused_parens_around_return_type() -> (u32) {
+LL + pub fn unused_parens_around_return_type() -> u32 {
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/lint-unnecessary-parens.rs:25:9
    |
 LL |         (5)
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (5)
+LL +         5
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/lint-unnecessary-parens.rs:27:5
    |
 LL |     (5)
-   |     ^^^ help: remove these parentheses
+   |     ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     (5)
+LL +     5
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:44:31
    |
 LL | pub const CONST_ITEM: usize = (10);
-   |                               ^^^^ help: remove these parentheses
+   |                               ^  ^
+   |
+help: remove these parentheses
+   |
+LL - pub const CONST_ITEM: usize = (10);
+LL + pub const CONST_ITEM: usize = 10;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:45:33
    |
 LL | pub static STATIC_ITEM: usize = (10);
-   |                                 ^^^^ help: remove these parentheses
+   |                                 ^  ^
+   |
+help: remove these parentheses
+   |
+LL - pub static STATIC_ITEM: usize = (10);
+LL + pub static STATIC_ITEM: usize = 10;
+   | 
 
 error: unnecessary parentheses around function argument
   --> $DIR/lint-unnecessary-parens.rs:49:9
    |
 LL |     bar((true));
-   |         ^^^^^^ help: remove these parentheses
+   |         ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     bar((true));
+LL +     bar(true);
+   | 
 
 error: unnecessary parentheses around `if` condition
   --> $DIR/lint-unnecessary-parens.rs:51:8
    |
 LL |     if (true) {}
-   |        ^^^^^^ help: remove these parentheses
+   |        ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     if (true) {}
+LL +     if true {}
+   | 
 
 error: unnecessary parentheses around `while` condition
   --> $DIR/lint-unnecessary-parens.rs:52:11
    |
 LL |     while (true) {}
-   |           ^^^^^^ help: remove these parentheses
+   |           ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     while (true) {}
+LL +     while true {}
+   | 
 
 error: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:53:11
    |
 LL |     match (true) {
-   |           ^^^^^^ help: remove these parentheses
+   |           ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     match (true) {
+LL +     match true {
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:56:16
    |
 LL |     if let 1 = (1) {}
-   |                ^^^ help: remove these parentheses
+   |                ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if let 1 = (1) {}
+LL +     if let 1 = 1 {}
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:57:19
    |
 LL |     while let 1 = (2) {}
-   |                   ^^^ help: remove these parentheses
+   |                   ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     while let 1 = (2) {}
+LL +     while let 1 = 2 {}
+   | 
 
 error: unnecessary parentheses around method argument
   --> $DIR/lint-unnecessary-parens.rs:73:24
    |
 LL |     X { y: false }.foo((true));
-   |                        ^^^^^^ help: remove these parentheses
+   |                        ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     X { y: false }.foo((true));
+LL +     X { y: false }.foo(true);
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:75:18
    |
 LL |     let mut _a = (0);
-   |                  ^^^ help: remove these parentheses
+   |                  ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     let mut _a = (0);
+LL +     let mut _a = 0;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:76:10
    |
 LL |     _a = (0);
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     _a = (0);
+LL +     _a = 0;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:77:11
    |
 LL |     _a += (1);
-   |           ^^^ help: remove these parentheses
+   |           ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     _a += (1);
+LL +     _a += 1;
+   | 
 
 error: aborting due to 17 previous errors
 
index cad2514625588e36c89a9de4c127459f0aebf332..255772ff40261160a1874bd94642806d32bb9357 100644 (file)
@@ -10,13 +10,18 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/suggestions.rs:48:31
    |
 LL |         let mut registry_no = (format!("NX-{}", 74205));
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |                               ^                       ^
    |
 note: the lint level is defined here
   --> $DIR/suggestions.rs:4:21
    |
 LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
    |                     ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -         let mut registry_no = (format!("NX-{}", 74205));
+LL +         let mut registry_no = format!("NX-{}", 74205);
+   | 
 
 warning: variable does not need to be mutable
   --> $DIR/suggestions.rs:48:13
index e6d0a359c5ca7d857e935ca3004cc4039e54b4c5..677b96d3f32f082cee633cb9b8631b5241844ce7 100644 (file)
@@ -2,151 +2,294 @@ error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:16:9
    |
 LL |     let (a) = 0;
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
    |
 note: the lint level is defined here
   --> $DIR/issue-54538-unused-parens-lint.rs:13:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let (a) = 0;
+LL +     let a = 0;
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:17:9
    |
 LL |     for (a) in 0..1 {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     for (a) in 0..1 {}
+LL +     for a in 0..1 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:18:12
    |
 LL |     if let (a) = 0 {}
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if let (a) = 0 {}
+LL +     if let a = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:19:15
    |
 LL |     while let (a) = 0 {}
-   |               ^^^ help: remove these parentheses
+   |               ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     while let (a) = 0 {}
+LL +     while let a = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:20:12
    |
 LL |     fn foo((a): u8) {}
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     fn foo((a): u8) {}
+LL +     fn foo(a: u8) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:21:14
    |
 LL |     let _ = |(a): u8| 0;
-   |              ^^^ help: remove these parentheses
+   |              ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     let _ = |(a): u8| 0;
+LL +     let _ = |a: u8| 0;
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:49:12
    |
 LL |     if let (0 | 1) = 0 {}
-   |            ^^^^^^^ help: remove these parentheses
+   |            ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let (0 | 1) = 0 {}
+LL +     if let 0 | 1 = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:50:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
-   |             ^^^^^^^ help: remove these parentheses
+   |             ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let ((0 | 1),) = (0,) {}
+LL +     if let (0 | 1,) = (0,) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:51:13
    |
 LL |     if let [(0 | 1)] = [0] {}
-   |             ^^^^^^^ help: remove these parentheses
+   |             ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let [(0 | 1)] = [0] {}
+LL +     if let [0 | 1] = [0] {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:52:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
-   |                ^^^^^^^ help: remove these parentheses
+   |                ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let 0 | (1 | 2) = 0 {}
+LL +     if let 0 | 1 | 2 = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:54:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
-   |               ^^^^^^^ help: remove these parentheses
+   |               ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let TS((0 | 1)) = TS(0) {}
+LL +     if let TS(0 | 1) = TS(0) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:56:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
-   |                    ^^^^^^^ help: remove these parentheses
+   |                    ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+LL +     if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:66:9
    |
 LL |         (_) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (_) => {}
+LL +         _ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:67:9
    |
 LL |         (y) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (y) => {}
+LL +         y => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:68:9
    |
 LL |         (ref r) => {}
-   |         ^^^^^^^ help: remove these parentheses
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (ref r) => {}
+LL +         ref r => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:69:9
    |
 LL |         (e @ 1...2) => {}
-   |         ^^^^^^^^^^^ help: remove these parentheses
+   |         ^         ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ 1...2) => {}
+LL +         e @ 1...2 => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:75:9
    |
 LL |         (e @ &(1...2)) => {}
-   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+   |         ^            ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ &(1...2)) => {}
+LL +         e @ &(1...2) => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:76:10
    |
 LL |         &(_) => {}
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         &(_) => {}
+LL +         &_ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:87:9
    |
 LL |         (_) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (_) => {}
+LL +         _ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:88:9
    |
 LL |         (y) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (y) => {}
+LL +         y => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:89:9
    |
 LL |         (ref r) => {}
-   |         ^^^^^^^ help: remove these parentheses
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (ref r) => {}
+LL +         ref r => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:90:9
    |
 LL |         (e @ 1..=2) => {}
-   |         ^^^^^^^^^^^ help: remove these parentheses
+   |         ^         ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ 1..=2) => {}
+LL +         e @ 1..=2 => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:96:9
    |
 LL |         (e @ &(1..=2)) => {}
-   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+   |         ^            ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ &(1..=2)) => {}
+LL +         e @ &(1..=2) => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:97:10
    |
 LL |         &(_) => {}
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         &(_) => {}
+LL +         &_ => {}
+   | 
 
 error: aborting due to 24 previous errors
 
index 3f6260dc6e19e29211f9207c03d0f306857a0a80..a715093df4c329c34e40fc372b49e948b1b0bfbc 100644 (file)
@@ -2,49 +2,83 @@ error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29
    |
 LL |         while let Some(_) = ({yield}) {}
-   |                             ^^^^^^^^^ help: remove these parentheses
+   |                             ^       ^
    |
 note: the lint level is defined here
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24
    |
 LL | #![deny(unused_braces, unused_parens)]
    |                        ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -         while let Some(_) = ({yield}) {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29
    |
 LL |         while let Some(_) = ((yield)) {}
-   |                             ^^^^^^^^^ help: remove these parentheses
+   |                             ^       ^
+   |
+help: remove these parentheses
+   |
+LL -         while let Some(_) = ((yield)) {}
+LL +         while let Some(_) = (yield) {}
+   | 
 
 error: unnecessary braces around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10
    |
 LL |         {{yield}};
-   |          ^^^^^^^ help: remove these braces
+   |          ^     ^
    |
 note: the lint level is defined here
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9
    |
 LL | #![deny(unused_braces, unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -         {{yield}};
+LL +         {yield};
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10
    |
 LL |         {( yield )};
-   |          ^^^^^^^^^ help: remove these parentheses
+   |          ^^     ^^
+   |
+help: remove these parentheses
+   |
+LL -         {( yield )};
+LL +         {yield};
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30
    |
 LL |         while let Some(_) = {(yield)} {}
-   |                              ^^^^^^^ help: remove these parentheses
+   |                              ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         while let Some(_) = {(yield)} {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: unnecessary braces around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30
    |
 LL |         while let Some(_) = {{yield}} {}
-   |                              ^^^^^^^ help: remove these braces
+   |                              ^     ^
+   |
+help: remove these braces
+   |
+LL -         while let Some(_) = {{yield}} {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: aborting due to 6 previous errors
 
index 8fa5dfde61db06eba3999604f7b2629ef8f52b8c..7d6fef00ac1a4078357771226ddb4d6e0ed8955a 100644 (file)
@@ -2,43 +2,71 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/unused_braces.rs:10:13
    |
 LL |     let _ = (7);
-   |             ^^^ help: remove these parentheses
+   |             ^ ^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces.rs:4:24
    |
 LL | #![warn(unused_braces, unused_parens)]
    |                        ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let _ = (7);
+LL +     let _ = 7;
+   | 
 
 warning: unnecessary braces around `if` condition
   --> $DIR/unused_braces.rs:26:8
    |
 LL |     if { true } {
-   |        ^^^^^^^^ help: remove these braces
+   |        ^^    ^^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces.rs:4:9
    |
 LL | #![warn(unused_braces, unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     if { true } {
+LL +     if true {
+   | 
 
 warning: unnecessary braces around `while` condition
   --> $DIR/unused_braces.rs:30:11
    |
 LL |     while { false } {
-   |           ^^^^^^^^^ help: remove these braces
+   |           ^^     ^^
+   |
+help: remove these braces
+   |
+LL -     while { false } {
+LL +     while false {
+   | 
 
 warning: unnecessary braces around const expression
   --> $DIR/unused_braces.rs:34:17
    |
 LL |     let _: [u8; { 3 }];
-   |                 ^^^^^ help: remove these braces
+   |                 ^^ ^^
+   |
+help: remove these braces
+   |
+LL -     let _: [u8; { 3 }];
+LL +     let _: [u8; 3];
+   | 
 
 warning: unnecessary braces around function argument
   --> $DIR/unused_braces.rs:37:13
    |
 LL |     consume({ 7 });
-   |             ^^^^^ help: remove these braces
+   |             ^^ ^^
+   |
+help: remove these braces
+   |
+LL -     consume({ 7 });
+LL +     consume(7);
+   | 
 
 warning: 5 warnings emitted
 
index f018c46fcd3c6ae3772d60b184e2267c3f61fd77..5a5326cab3b1de5391d1d2c7f5eec0144337ba43 100644 (file)
@@ -2,13 +2,18 @@ warning: unnecessary braces around function argument
   --> $DIR/unused_braces_borrow.rs:24:13
    |
 LL |     consume({ a.b });
-   |             ^^^^^^^ help: remove these braces
+   |             ^^   ^^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces_borrow.rs:4:9
    |
 LL | #![warn(unused_braces)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     consume({ a.b });
+LL +     consume(a.b);
+   | 
 
 warning: 1 warning emitted
 
index 09f0fc90032dc1402a29c9e9bb07262552d46254..498c25d2e1c44ed4a2318ef21f6170e9861a2b0c 100644 (file)
@@ -1,14 +1,19 @@
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
   --> $DIR/unused_parens_json_suggestion.rs:16:14
    |
 LL |     let _a = (1 / (2 + 3));
-   |              ^^^^^^^^^^^^^ help: remove these parentheses
+   |              ^           ^
    |
 note: the lint level is defined here
   --> $DIR/unused_parens_json_suggestion.rs:10:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let _a = (1 / (2 + 3));
+LL +     let _a = 1 / (2 + 3);
+   | 
 
 "}
 {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
index 5fb67fd7c95a3a99a8ff0cbbd4c7c9cbab1f4c97..08291b10fcc204f284fe3347f193846bc10c1b51 100644 (file)
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":"    if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:17:8
    |
 LL |     if (_b) {
-   |        ^^^^ help: remove these parentheses
+   |        ^  ^
    |
 note: the lint level is defined here
   --> $DIR/unused_parens_remove_json_suggestion.rs:10:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     if (_b) {
+LL +     if _b {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":"    if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:28:7
    |
 LL |     if(c) {
-   |       ^^^ help: remove these parentheses
+   |       ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if(c) {
+LL +     if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":"    if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
   --> $DIR/unused_parens_remove_json_suggestion.rs:32:8
    |
 LL |     if (c){
-   |        ^^^ help: remove these parentheses
+   |        ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if (c){
+LL +     if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
   --> $DIR/unused_parens_remove_json_suggestion.rs:36:11
    |
 LL |     while (false && true){
-   |           ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |           ^             ^
+   |
+help: remove these parentheses
+   |
+LL -     while (false && true){
+LL +     while false && true {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":"        if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:37:12
    |
 LL |         if (c) {
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         if (c) {
+LL +         if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":"    while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:43:10
    |
 LL |     while(true && false) {
-   |          ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |          ^             ^
+   |
+help: remove these parentheses
+   |
+LL -     while(true && false) {
+LL +     while true && false {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
   --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
-   |                  ^^^^^^^^ help: remove these parentheses
+   |                  ^      ^
+   |
+help: remove these parentheses
+   |
+LL -         for _ in (0 .. 3){
+LL +         for _ in 0 .. 3 {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
-   |              ^^^^^^^^ help: remove these parentheses
+   |              ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     for _ in (0 .. 3) {
+LL +     for _ in 0 .. 3 {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":"        while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:50:15
    |
 LL |         while (true && false) {
-   |               ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |               ^             ^
+   |
+help: remove these parentheses
+   |
+LL -         while (true && false) {
+LL +         while true && false {
+   | 
 
 "}
 {"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors
diff --git a/src/test/ui/llvm-asm/issue-37433.rs b/src/test/ui/llvm-asm/issue-37433.rs
new file mode 100644 (file)
index 0000000..1c362e8
--- /dev/null
@@ -0,0 +1,12 @@
+// build-fail
+// ignore-emscripten no llvm_asm! support
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+fn main() {
+    unsafe {
+        llvm_asm!("" :: "r"(""));
+        //~^ ERROR: invalid value for constraint in inline assembly
+    }
+}
diff --git a/src/test/ui/llvm-asm/issue-37433.stderr b/src/test/ui/llvm-asm/issue-37433.stderr
new file mode 100644 (file)
index 0000000..44a8eb3
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+  --> $DIR/issue-37433.rs:9:29
+   |
+LL |         llvm_asm!("" :: "r"(""));
+   |                             ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
index 3a860f508ff787845eb9efd34a469f9fb64151fc..68a19a8f6f7170c9b9a95deb61292acab941bc66 100644 (file)
@@ -1,7 +1,7 @@
 // check-pass
+#![feature(label_break_value)]
 
-
-// Issue #21633: reject duplicate loop labels in function bodies.
+// Issue #21633: reject duplicate loop labels and block labels in function bodies.
 //
 // This is testing the generalization (to the whole function body)
 // discussed here:
@@ -26,6 +26,8 @@ pub fn foo() {
     { 'lt: loop { break; } }
     { 'lt: while let Some(_) = None::<i32> { break; } }
                                          //~^ WARN label name `'lt` shadows a label name that is already in scope
+    { 'bl: {} }
+    { 'bl: {} } //~ WARN label name `'bl` shadows a label name that is already in scope
 }
 
 
index 6c53d04e107900b24ffd03694e02e9d4f16e0809..2c372fcff7a12aa1c6cc37ac90c1b2e48e1b6751 100644 (file)
@@ -62,5 +62,13 @@ LL |     { 'lt: loop { break; } }
 LL |     { 'lt: while let Some(_) = None::<i32> { break; } }
    |       ^^^ label `'lt` already in scope
 
-warning: 8 warnings emitted
+warning: label name `'bl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels-2.rs:30:7
+   |
+LL |     { 'bl: {} }
+   |       --- first declared here
+LL |     { 'bl: {} }
+   |       ^^^ label `'bl` already in scope
+
+warning: 9 warnings emitted
 
index d9334ce3857184a641e31d87b3e7abaeb13b0e22..c34bcf3df1d76253870af5d66e5837acb9af1772 100644 (file)
@@ -1,8 +1,7 @@
 // check-pass
+#![feature(label_break_value)]
 
-
-// Issue #21633: reject duplicate loop labels in function bodies.
-// This is testing the exact cases that are in the issue description.
+// Issue #21633: reject duplicate loop labels and block labels in function bodies.
 
 #[allow(unused_labels)]
 fn foo() {
@@ -24,6 +23,8 @@ fn foo() {
     'lt: loop { break; }
     'lt: while let Some(_) = None::<i32> { break; }
                                    //~^ WARN label name `'lt` shadows a label name that is already in scope
+    'bl: {}
+    'bl: {} //~ WARN label name `'bl` shadows a label name that is already in scope
 }
 
 // Note however that it is okay for the same label to be reused in
@@ -33,6 +34,8 @@ fn foo() {
 impl S {
     fn m1(&self) { 'okay: loop { break 'okay; } }
     fn m2(&self) { 'okay: loop { break 'okay; } }
+    fn m3(&self) { 'okay: { break 'okay; } }
+    fn m4(&self) { 'okay: { break 'okay; } }
 }
 
 
@@ -40,5 +43,7 @@ pub fn main() {
     let s = S;
     s.m1();
     s.m2();
+    s.m3();
+    s.m4();
     foo();
 }
index 5bdf64849f30554935a216f7cf0adfff228a8b63..3bf3af763ecfc9aa80fb3ea306c709e0da693f6b 100644 (file)
@@ -1,5 +1,5 @@
 warning: label name `'fl` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:10:5
+  --> $DIR/loops-reject-duplicate-labels.rs:9:5
    |
 LL |     'fl: for _ in 0..10 { break; }
    |     --- first declared here
@@ -7,7 +7,7 @@ LL |     'fl: loop { break; }
    |     ^^^ label `'fl` already in scope
 
 warning: label name `'lf` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:13:5
+  --> $DIR/loops-reject-duplicate-labels.rs:12:5
    |
 LL |     'lf: loop { break; }
    |     --- first declared here
@@ -15,7 +15,7 @@ LL |     'lf: for _ in 0..10 { break; }
    |     ^^^ label `'lf` already in scope
 
 warning: label name `'wl` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:15:5
+  --> $DIR/loops-reject-duplicate-labels.rs:14:5
    |
 LL |     'wl: while 2 > 1 { break; }
    |     --- first declared here
@@ -23,7 +23,7 @@ LL |     'wl: loop { break; }
    |     ^^^ label `'wl` already in scope
 
 warning: label name `'lw` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:17:5
+  --> $DIR/loops-reject-duplicate-labels.rs:16:5
    |
 LL |     'lw: loop { break; }
    |     --- first declared here
@@ -31,7 +31,7 @@ LL |     'lw: while 2 > 1 { break; }
    |     ^^^ label `'lw` already in scope
 
 warning: label name `'fw` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:19:5
+  --> $DIR/loops-reject-duplicate-labels.rs:18:5
    |
 LL |     'fw: for _ in 0..10 { break; }
    |     --- first declared here
@@ -39,7 +39,7 @@ LL |     'fw: while 2 > 1 { break; }
    |     ^^^ label `'fw` already in scope
 
 warning: label name `'wf` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:21:5
+  --> $DIR/loops-reject-duplicate-labels.rs:20:5
    |
 LL |     'wf: while 2 > 1 { break; }
    |     --- first declared here
@@ -47,7 +47,7 @@ LL |     'wf: for _ in 0..10 { break; }
    |     ^^^ label `'wf` already in scope
 
 warning: label name `'tl` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:23:5
+  --> $DIR/loops-reject-duplicate-labels.rs:22:5
    |
 LL |     'tl: while let Some(_) = None::<i32> { break; }
    |     --- first declared here
@@ -55,12 +55,20 @@ LL |     'tl: loop { break; }
    |     ^^^ label `'tl` already in scope
 
 warning: label name `'lt` shadows a label name that is already in scope
-  --> $DIR/loops-reject-duplicate-labels.rs:25:5
+  --> $DIR/loops-reject-duplicate-labels.rs:24:5
    |
 LL |     'lt: loop { break; }
    |     --- first declared here
 LL |     'lt: while let Some(_) = None::<i32> { break; }
    |     ^^^ label `'lt` already in scope
 
-warning: 8 warnings emitted
+warning: label name `'bl` shadows a label name that is already in scope
+  --> $DIR/loops-reject-duplicate-labels.rs:27:5
+   |
+LL |     'bl: {}
+   |     --- first declared here
+LL |     'bl: {}
+   |     ^^^ label `'bl` already in scope
+
+warning: 9 warnings emitted
 
index 3212b78b08cd8e6e7d1ecc00d18793614bf27568..ce2d07eb06a4d766e8fcbc86ade0b87b98fb8a09 100644 (file)
@@ -1,10 +1,10 @@
 // check-pass
-
+#![feature(label_break_value)]
 #![allow(dead_code, unused_variables)]
 
-// Issue #21633:  reject duplicate loop labels in function bodies.
+// Issue #21633:  reject duplicate loop labels and block labels in function bodies.
 //
-// Test rejection of lifetimes in *expressions* that shadow loop labels.
+// Test rejection of lifetimes in *expressions* that shadow labels.
 
 fn foo() {
     // Reusing lifetime `'a` in function item is okay.
@@ -23,8 +23,13 @@ struct S1<'a> { x: &'a i8 } impl<'a> S1<'a> { fn m(&self) {} }
         assert_eq!((*b)(&z), z);
         break 'a;
     }
-}
 
+    'b: {
+        let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
+        //~^ WARN lifetime name `'b` shadows a label name that is already in scope
+        break 'b;
+    }
+}
 
 pub fn main() {
     foo();
index dcee1a8009053c4eaf0ba2aea6bc07168397e045..9702b71600b5e572878742d1bc26542ae750ff84 100644 (file)
@@ -6,5 +6,13 @@ LL |     'a: loop {
 LL |         let b = Box::new(|x: &i8| *x) as Box<dyn for <'a> Fn(&'a i8) -> i8>;
    |                                                       ^^ label `'a` already in scope
 
-warning: 1 warning emitted
+warning: lifetime name `'b` shadows a label name that is already in scope
+  --> $DIR/loops-reject-lifetime-shadowing-label.rs:28:55
+   |
+LL |     'b: {
+   |     -- first declared here
+LL |         let b = Box::new(|x: &()| ()) as Box<dyn for <'b> Fn(&'b ())>;
+   |                                                       ^^ label `'b` already in scope
+
+warning: 2 warnings emitted
 
diff --git a/src/test/ui/macros/auxiliary/define-macro.rs b/src/test/ui/macros/auxiliary/define-macro.rs
new file mode 100644 (file)
index 0000000..4956907
--- /dev/null
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! define_macro {
+    ($i:ident) => {
+        macro_rules! $i { () => {} }
+    }
+}
diff --git a/src/test/ui/macros/lint-trailing-macro-call.rs b/src/test/ui/macros/lint-trailing-macro-call.rs
new file mode 100644 (file)
index 0000000..f8e8475
--- /dev/null
@@ -0,0 +1,16 @@
+// check-pass
+//
+// Ensures that we properly lint
+// a removed 'expression' resulting from a macro
+// in trailing expression position
+
+macro_rules! expand_it {
+    () => {
+        #[cfg(FALSE)] 25; //~  WARN trailing semicolon in macro
+                          //~| WARN this was previously
+    }
+}
+
+fn main() {
+    expand_it!()
+}
diff --git a/src/test/ui/macros/lint-trailing-macro-call.stderr b/src/test/ui/macros/lint-trailing-macro-call.stderr
new file mode 100644 (file)
index 0000000..a98a559
--- /dev/null
@@ -0,0 +1,18 @@
+warning: trailing semicolon in macro used in expression position
+  --> $DIR/lint-trailing-macro-call.rs:9:25
+   |
+LL |         #[cfg(FALSE)] 25;
+   |                         ^
+...
+LL |     expand_it!()
+   |     ------------ in this macro invocation
+   |
+   = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+   = note: macro invocations at the end of a block are treated as expressions
+   = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it`
+   = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/macros/out-of-order-shadowing.rs b/src/test/ui/macros/out-of-order-shadowing.rs
new file mode 100644 (file)
index 0000000..a0d1a97
--- /dev/null
@@ -0,0 +1,10 @@
+// aux-build:define-macro.rs
+
+macro_rules! bar { () => {} }
+define_macro!(bar);
+bar!(); //~ ERROR `bar` is ambiguous
+
+macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
+m!();
+
+fn main() {}
diff --git a/src/test/ui/macros/out-of-order-shadowing.stderr b/src/test/ui/macros/out-of-order-shadowing.stderr
new file mode 100644 (file)
index 0000000..1db31e0
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
+  --> $DIR/out-of-order-shadowing.rs:5:1
+   |
+LL | bar!();
+   | ^^^ ambiguous name
+   |
+note: `bar` could refer to the macro defined here
+  --> $DIR/out-of-order-shadowing.rs:4:1
+   |
+LL | define_macro!(bar);
+   | ^^^^^^^^^^^^^^^^^^^
+note: `bar` could also refer to the macro defined here
+  --> $DIR/out-of-order-shadowing.rs:3:1
+   |
+LL | macro_rules! bar { () => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `define_macro` (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 E0659`.
diff --git a/src/test/ui/match/guards.rs b/src/test/ui/match/guards.rs
new file mode 100644 (file)
index 0000000..10a4bb6
--- /dev/null
@@ -0,0 +1,20 @@
+// run-pass
+
+#![allow(non_shorthand_field_patterns)]
+
+#[derive(Copy, Clone)]
+struct Pair { x: isize, y: isize }
+
+pub fn main() {
+    let a: isize =
+        match 10 { x if x < 7 => { 1 } x if x < 11 => { 2 } 10 => { 3 } _ => { 4 } };
+    assert_eq!(a, 2);
+
+    let b: isize =
+        match (Pair {x: 10, y: 20}) {
+          x if x.x < 5 && x.y < 5 => { 1 }
+          Pair {x: x, y: y} if x == 10 && y == 20 => { 2 }
+          Pair {x: _x, y: _y} => { 3 }
+        };
+    assert_eq!(b, 2);
+}
diff --git a/src/test/ui/match/issue-33498.rs b/src/test/ui/match/issue-33498.rs
new file mode 100644 (file)
index 0000000..9c8a97e
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+#![allow(unused_variables)]
+pub fn main() {
+    let x = (0, 2);
+
+    match x {
+        (0, ref y) => {}
+        (y, 0) => {}
+        _ => (),
+    }
+}
diff --git a/src/test/ui/match/issue-41255.rs b/src/test/ui/match/issue-41255.rs
new file mode 100644 (file)
index 0000000..9d7072f
--- /dev/null
@@ -0,0 +1,51 @@
+// Matching against float literals should result in a linter error
+
+#![feature(exclusive_range_pattern)]
+#![feature(half_open_range_patterns)]
+#![allow(unused)]
+#![forbid(illegal_floating_point_literal_pattern)]
+
+fn main() {
+    let x = 42.0;
+    match x {
+        5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                   //~| WARNING hard error
+        5.0f32 => {}, //~ ERROR floating-point types cannot be used in patterns
+                      //~| WARNING hard error
+        -5.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                    //~| WARNING hard error
+        1.0 .. 33.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+                           //~| ERROR floating-point types cannot be used in patterns
+                           //~| WARNING hard error
+        39.0 ..= 70.0 => {}, //~ ERROR floating-point types cannot be used in patterns
+                             //~| ERROR floating-point types cannot be used in patterns
+                             //~| WARNING hard error
+                             //~| WARNING hard error
+
+        ..71.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| WARNING this was previously accepted by the compiler
+        ..=72.0 => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| WARNING this was previously accepted by the compiler
+        71.0.. => {}
+        //~^ ERROR floating-point types cannot be used in patterns
+        //~| WARNING this was previously accepted by the compiler
+        _ => {},
+    };
+    let y = 5.0;
+    // Same for tuples
+    match (x, 5) {
+        (3.14, 1) => {}, //~ ERROR floating-point types cannot be used
+                         //~| WARNING hard error
+        _ => {},
+    }
+    // Or structs
+    struct Foo { x: f32 };
+    match (Foo { x }) {
+        Foo { x: 2.0 } => {}, //~ ERROR floating-point types cannot be used
+                              //~| WARNING hard error
+        _ => {},
+    }
+}
diff --git a/src/test/ui/match/issue-41255.stderr b/src/test/ui/match/issue-41255.stderr
new file mode 100644 (file)
index 0000000..bf81c8d
--- /dev/null
@@ -0,0 +1,115 @@
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:11:9
+   |
+LL |         5.0 => {},
+   |         ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-41255.rs:6:11
+   |
+LL | #![forbid(illegal_floating_point_literal_pattern)]
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:13:9
+   |
+LL |         5.0f32 => {},
+   |         ^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:15:10
+   |
+LL |         -5.0 => {},
+   |          ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:17:9
+   |
+LL |         1.0 .. 33.0 => {},
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:17:16
+   |
+LL |         1.0 .. 33.0 => {},
+   |                ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:21:9
+   |
+LL |         39.0 ..= 70.0 => {},
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:21:18
+   |
+LL |         39.0 ..= 70.0 => {},
+   |                  ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:26:11
+   |
+LL |         ..71.0 => {}
+   |           ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:29:12
+   |
+LL |         ..=72.0 => {}
+   |            ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:32:9
+   |
+LL |         71.0.. => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:40:10
+   |
+LL |         (3.14, 1) => {},
+   |          ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+  --> $DIR/issue-41255.rs:47:18
+   |
+LL |         Foo { x: 2.0 } => {},
+   |                  ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/match/issue-56685.rs b/src/test/ui/match/issue-56685.rs
new file mode 100644 (file)
index 0000000..f320c99
--- /dev/null
@@ -0,0 +1,44 @@
+#![allow(dead_code)]
+#![deny(unused_variables)]
+
+// This test aims to check that unused variable suggestions update bindings in all
+// match arms.
+
+fn main() {
+    enum E {
+        A(i32,),
+        B(i32,),
+    }
+
+    match E::A(1) {
+        E::A(x) | E::B(x) => {}
+        //~^ ERROR unused variable: `x`
+    }
+
+    enum F {
+        A(i32, i32,),
+        B(i32, i32,),
+        C(i32, i32,),
+    }
+
+    let _ = match F::A(1, 2) {
+        F::A(x, y) | F::B(x, y) => { y },
+        //~^ ERROR unused variable: `x`
+        F::C(a, b) => { 3 }
+        //~^ ERROR unused variable: `a`
+        //~^^ ERROR unused variable: `b`
+    };
+
+    let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+    //~^ ERROR unused variable: `x`
+        y
+    } else {
+        3
+    };
+
+    while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+    //~^ ERROR unused variable: `x`
+        let _ = y;
+        break;
+    }
+}
diff --git a/src/test/ui/match/issue-56685.stderr b/src/test/ui/match/issue-56685.stderr
new file mode 100644 (file)
index 0000000..ccf357d
--- /dev/null
@@ -0,0 +1,63 @@
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:14:14
+   |
+LL |         E::A(x) | E::B(x) => {}
+   |              ^         ^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-56685.rs:2:9
+   |
+LL | #![deny(unused_variables)]
+   |         ^^^^^^^^^^^^^^^^
+help: if this is intentional, prefix it with an underscore
+   |
+LL |         E::A(_x) | E::B(_x) => {}
+   |              ~~         ~~
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:25:14
+   |
+LL |         F::A(x, y) | F::B(x, y) => { y },
+   |              ^            ^
+   |
+help: if this is intentional, prefix it with an underscore
+   |
+LL |         F::A(_x, y) | F::B(_x, y) => { y },
+   |              ~~            ~~
+
+error: unused variable: `a`
+  --> $DIR/issue-56685.rs:27:14
+   |
+LL |         F::C(a, b) => { 3 }
+   |              ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+  --> $DIR/issue-56685.rs:27:17
+   |
+LL |         F::C(a, b) => { 3 }
+   |                 ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:32:25
+   |
+LL |     let _ = if let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+   |                         ^            ^
+   |
+help: if this is intentional, prefix it with an underscore
+   |
+LL |     let _ = if let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+   |                         ~~            ~~
+
+error: unused variable: `x`
+  --> $DIR/issue-56685.rs:39:20
+   |
+LL |     while let F::A(x, y) | F::B(x, y) = F::A(1, 2) {
+   |                    ^            ^
+   |
+help: if this is intentional, prefix it with an underscore
+   |
+LL |     while let F::A(_x, y) | F::B(_x, y) = F::A(1, 2) {
+   |                    ~~            ~~
+
+error: aborting due to 6 previous errors
+
index 75c1f695d7e3a5dcc0fcf008484353a6cf6182ba..4adeebe2a591d260fdeb56a258b9b69cabbefa62 100644 (file)
@@ -9,7 +9,7 @@ LL |     let x: u32 = 22_usize;
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     let x: u32 = 22_u32;
-   |                  ~~~~~~
+   |                     ~~~
 
 error: aborting due to previous error
 
index 7985357d0aed6507c01eb0f5bdf1c9188b99e2ca..012071df2bb52d8cb87a498ad9687ed61bfec85b 100644 (file)
@@ -9,7 +9,7 @@ LL |     let x: u32 = 22_usize;
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     let x: u32 = 22_u32;
-   |                  ~~~~~~
+   |                     ~~~
 
 error: aborting due to previous error
 
index e725e74efc2b444e75c68c2b3111e499c62066cc..4b494c961158a32de6db7a2d45d25c5509c3916b 100644 (file)
@@ -17,7 +17,7 @@ LL |     let y: usize = x.foo();
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     let y: usize = x.foo().try_into().unwrap();
-   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                           ++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mid-path-type-params.rs b/src/test/ui/mid-path-type-params.rs
deleted file mode 100644 (file)
index a812820..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-struct S<T> {
-    contents: T,
-}
-
-impl<T> S<T> {
-    fn new<U>(x: T, _: U) -> S<T> {
-        S {
-            contents: x,
-        }
-    }
-}
-
-trait Trait<T> {
-    fn new<U>(x: T, y: U) -> Self;
-}
-
-struct S2 {
-    contents: isize,
-}
-
-impl Trait<isize> for S2 {
-    fn new<U>(x: isize, _: U) -> S2 {
-        S2 {
-            contents: x,
-        }
-    }
-}
-
-pub fn main() {
-    let _ = S::<isize>::new::<f64>(1, 1.0);
-    let _: S2 = Trait::<isize>::new::<f64>(1, 1.0);
-}
diff --git a/src/test/ui/mir/remove-zsts-query-cycle.rs b/src/test/ui/mir/remove-zsts-query-cycle.rs
new file mode 100644 (file)
index 0000000..8f93c6c
--- /dev/null
@@ -0,0 +1,16 @@
+// Regression test for #88972. Used to cause a query cycle:
+//   optimized mir -> remove zsts -> layout of a generator -> optimized mir.
+//
+// edition:2018
+// compile-flags: --crate-type=lib
+// build-pass
+
+pub async fn listen() -> Result<(), std::io::Error> {
+    let f = do_async();
+    std::mem::forget(f);
+    Ok(())
+}
+
+pub async fn do_async() {
+    listen().await.unwrap()
+}
index c8e81c93e2cbd432db2ac1575317f6b1dd83b3a8..1f2e169c6813c9eefc4be9839f08a7c8576a141c 100644 (file)
@@ -33,7 +33,9 @@ LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     foo(f);
-   |         ^ expected signature of `fn(usize) -> _`
+   |     --- ^ expected signature of `fn(usize) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/E0631.rs:3:11
@@ -48,7 +50,9 @@ LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     bar(f);
-   |         ^ expected signature of `fn(usize) -> _`
+   |     --- ^ expected signature of `fn(usize) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/E0631.rs:4:11
index 679001724640490576203304ed877226486dfb2e..e8fcf80e940d29b7c152fd791fa359e9978f2002 100644 (file)
@@ -119,7 +119,9 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it
   --> $DIR/closure-arg-count.rs:24:57
    |
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
-   |                                                         ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 ...
 LL | fn foo() {}
    | -------- takes 0 arguments
@@ -130,13 +132,17 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t
 LL |     let bar = |i, x, y| i;
    |               --------- takes 3 distinct arguments
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
-   |                                                         ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:29:57
    |
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
-   |                                                         ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 ...
 LL | fn qux(x: usize, y: usize) {}
    | -------------------------- takes 2 distinct arguments
@@ -145,13 +151,17 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/closure-arg-count.rs:32:45
    |
 LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
-   |                                             ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+   |                                         --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+   |                                         |
+   |                                         required by a bound introduced by this call
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:35:10
    |
 LL |     call(Foo);
-   |          ^^^ expected function that takes 0 arguments
+   |     ---- ^^^ expected function that takes 0 arguments
+   |     |
+   |     required by a bound introduced by this call
 ...
 LL | struct Foo(u8);
    | --------------- takes 1 argument
index afde894b3044d0cd2635b4921cfaf07612c6620c..ce1dde94b5dd021a74f7c42577121fb6745ea1fc 100644 (file)
@@ -5,7 +5,9 @@ LL | fn takes_mut(x: &mut isize) { }
    | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _`
 ...
 LL |     apply(&3, takes_mut);
-   |               ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+   |     -----     ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
@@ -20,7 +22,9 @@ LL | fn takes_imm(x: &isize) { }
    | ----------------------- found signature of `for<'r> fn(&'r isize) -> _`
 ...
 LL |     apply(&mut 3, takes_imm);
-   |                   ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+   |     -----         ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
index e480bb250b2a5e4596c97931fb1f6d7cb7d7c8cf..3e2ebf43b8c3a08264ae522a2db249b9d1589648 100644 (file)
@@ -11,7 +11,7 @@ LL |     write!(hello);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |                   ($arr.len() * size_of($arr[0])).try_into().unwrap());
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +                             +++++++++++++++++++++
 
 error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:22:19
index 7ab5224979897232ec39e0a19094fab79bb4460d..55e45a8f1625a6aa2d0d2b66e36f1e37038bc3f9 100644 (file)
@@ -7,7 +7,7 @@ LL |     foo(1u8);
 help: change the type of the numeric literal from `u8` to `u16`
    |
 LL |     foo(1u16);
-   |         ~~~~
+   |          ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:8:10
@@ -18,7 +18,7 @@ LL |     foo1(2f32);
 help: change the type of the numeric literal from `f32` to `f64`
    |
 LL |     foo1(2f64);
-   |          ~~~~
+   |           ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:10:10
@@ -29,7 +29,7 @@ LL |     foo2(3i16);
 help: change the type of the numeric literal from `i16` to `i32`
    |
 LL |     foo2(3i32);
-   |          ~~~~
+   |           ~~~
 
 error: aborting due to 3 previous errors
 
index ad59462e9bd441a1613da27dd2d69332b727f293..44ec28f53cc62d5a6ca4cbbc9120378206b1982a 100644 (file)
@@ -16,5 +16,6 @@ pub fn main() {
     let z = call_it(3, f);
     //~^ ERROR type mismatch
     //~| NOTE expected signature of `fn(isize, isize) -> _`
+    //~| NOTE required by a bound introduced by this call
     println!("{}", z);
 }
index 4406f8a9e58b40fa5b793fdd1c585380d01c2ed9..f9ef5bc4e39b3680f893345afe5496355d9574a8 100644 (file)
@@ -5,7 +5,9 @@ LL |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
    |                       ----------------------------- found signature of `fn(usize, isize) -> _`
 LL |
 LL |     let z = call_it(3, f);
-   |                        ^ expected signature of `fn(isize, isize) -> _`
+   |             -------    ^ expected signature of `fn(isize, isize) -> _`
+   |             |
+   |             required by a bound introduced by this call
    |
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-vtable-mismatch.rs:7:14
index 637b09fc04e5f38fab90fe70d0670bcd6fee4f7d..a8d8bd1d5fd008ed1785479ba47ca2f7ce8be75c 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 
 #![allow(non_upper_case_globals)]
+#![allow(dead_code)]
 /*!
  * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment,
  * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment
index 48baead074ac7d5e2442af585c2c0d95e24c0c22..7d3987f65608715ce3147fdbf44295120869b968 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unused_mut)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 #[derive(Clone)]
index 55b10e057d88cce761e898320d3adc27d6d684d1..d23a852433f4f9b478312061d6a78d16a9eacc5c 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unused_mut)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 #[derive(Clone)]
index 9427ba546a9c10468153db4e4547826cf02713d0..e12af2d45274315fcdef2ad9bfed6f3d1e4f2784 100644 (file)
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure
 LL |     let i = box 3;
    |         - captured outer variable
 LL |     let _f = to_fn(|| test(i));
-   |                            ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
+   |                    --------^-
+   |                    |       |
+   |                    |       move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
+   |                    captured by this `Fn` closure
 
 error: aborting due to previous error
 
index 172e257ebf04a5b007b91c7a38f833b7c3dc3d72..b3c77b13eafb4e0e352fe249769d8c533d11d8f8 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `Cell<i32>` cannot be shared between threads safely
   --> $DIR/mutexguard-sync.rs:11:15
    |
 LL |     test_sync(guard);
-   |               ^^^^^ `Cell<i32>` cannot be shared between threads safely
+   |     --------- ^^^^^ `Cell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required because of the requirements on the impl of `Sync` for `MutexGuard<'_, Cell<i32>>`
index e4e1071638876489ce44c60dec59d88f671efc59..b610857229201a156a3c5967e7cf11625dfd2f7d 100644 (file)
@@ -100,7 +100,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:33:11
    |
 LL |     check(m1::S{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -112,7 +114,9 @@ error[E0277]: the trait bound `c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:35:11
    |
 LL |     check(m2::S{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -124,7 +128,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:36:11
    |
 LL |     check(m2::S);
-   |           ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -136,7 +142,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:39:11
    |
 LL |     check(xm1::S{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -148,7 +156,9 @@ error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:41:11
    |
 LL |     check(xm2::S{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -160,7 +170,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:42:11
    |
 LL |     check(xm2::S);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -172,7 +184,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:55:11
    |
 LL |     check(m3::TS{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -184,7 +198,9 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi
   --> $DIR/namespace-mix.rs:56:11
    |
 LL |     check(m3::TS);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -196,7 +212,9 @@ error[E0277]: the trait bound `c::TS: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:57:11
    |
 LL |     check(m4::TS{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -208,7 +226,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:58:11
    |
 LL |     check(m4::TS);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -220,7 +240,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:61:11
    |
 LL |     check(xm3::TS{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -232,7 +254,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T
   --> $DIR/namespace-mix.rs:62:11
    |
 LL |     check(xm3::TS);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -244,7 +268,9 @@ error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:63:11
    |
 LL |     check(xm4::TS{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -256,7 +282,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:64:11
    |
 LL |     check(xm4::TS);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -268,7 +296,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:77:11
    |
 LL |     check(m5::US{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -280,7 +310,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:78:11
    |
 LL |     check(m5::US);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -292,7 +324,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:79:11
    |
 LL |     check(m6::US{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -304,7 +338,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:80:11
    |
 LL |     check(m6::US);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -316,7 +352,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:83:11
    |
 LL |     check(xm5::US{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -328,7 +366,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:84:11
    |
 LL |     check(xm5::US);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -340,7 +380,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:85:11
    |
 LL |     check(xm6::US{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -352,7 +394,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:86:11
    |
 LL |     check(xm6::US);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -364,7 +408,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:99:11
    |
 LL |     check(m7::V{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -376,7 +422,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:101:11
    |
 LL |     check(m8::V{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -388,7 +436,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:102:11
    |
 LL |     check(m8::V);
-   |           ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -400,7 +450,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:105:11
    |
 LL |     check(xm7::V{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -412,7 +464,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:107:11
    |
 LL |     check(xm8::V{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -424,7 +478,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:108:11
    |
 LL |     check(xm8::V);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -436,7 +492,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:121:11
    |
 LL |     check(m9::TV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -448,7 +506,9 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis
   --> $DIR/namespace-mix.rs:122:11
    |
 LL |     check(m9::TV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -460,7 +520,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:123:11
    |
 LL |     check(mA::TV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -472,7 +534,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:124:11
    |
 LL |     check(mA::TV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -484,7 +548,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:127:11
    |
 LL |     check(xm9::TV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -496,7 +562,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::
   --> $DIR/namespace-mix.rs:128:11
    |
 LL |     check(xm9::TV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -508,7 +576,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:129:11
    |
 LL |     check(xmA::TV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -520,7 +590,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:130:11
    |
 LL |     check(xmA::TV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -532,7 +604,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:143:11
    |
 LL |     check(mB::UV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -544,7 +618,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:144:11
    |
 LL |     check(mB::UV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -556,7 +632,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:145:11
    |
 LL |     check(mC::UV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -568,7 +646,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:146:11
    |
 LL |     check(mC::UV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -580,7 +660,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:149:11
    |
 LL |     check(xmB::UV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -592,7 +674,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:150:11
    |
 LL |     check(xmB::UV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -604,7 +688,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:151:11
    |
 LL |     check(xmC::UV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -616,7 +702,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:152:11
    |
 LL |     check(xmC::UV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
diff --git a/src/test/ui/never_type/expr-empty-ret.rs b/src/test/ui/never_type/expr-empty-ret.rs
new file mode 100644 (file)
index 0000000..ce8ffaf
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![allow(dead_code)]
+// Issue #521
+
+// pretty-expanded FIXME #23616
+
+fn f() {
+    let _x = match true {
+        true => { 10 }
+        false => { return }
+    };
+}
+
+pub fn main() { }
index 49dd0e267b8ea8f187ad806f0cf1a23f4c34bf59..e6e95ee613647a1cff34d4d4479a73ab32e75162 100644 (file)
@@ -5,7 +5,7 @@ LL |     let foo = Foo { x: &a };
    |                        ^^
    |                        |
    |                        borrowed value does not live long enough
-   |                        requires that `a` is borrowed for `'static`
+   |                        this usage requires that `a` is borrowed for `'static`
 LL |     loop { }
 LL | }
    | - `a` dropped here while still borrowed
index 67115a5ccdd4505738faecf3c1bf0e9f39b8124c..c9324f0422cdc4444d88921cff84884071898e92 100644 (file)
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn`
 LL |        let x = (vec![22], vec![44]);
    |            - captured outer variable
 LL |        expect_fn(|| drop(x.0));
-   |                          ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
+   |                  --------^^^-
+   |                  |       |
+   |                  |       move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
+   |                  captured by this `Fn` closure
 
 error: aborting due to previous error
 
index 36721f923f7da7846172b8cc7f4fac579465c949..dbc478e5b4c87e180a90ef84bb07b860e6d9c047 100644 (file)
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'_` as defined on the im
    |
 LL | impl Foo<'_> {
    |          ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/issue-55394.rs:9:9
    |
 LL |         Foo { bar }
index 6498ecfbe6f9b555d5a1d15e2a1a71b12313811a..dbb63b71af8a2799f8eb2177382e34da341cc649 100644 (file)
@@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im
    |
 LL | impl<'a> FromBox<'a> for C<'a> {
    |      ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/type-alias-free-regions.rs:17:9
    |
 LL |         C { f: b }
@@ -52,7 +52,7 @@ note: but, the lifetime must be valid for the lifetime `'a` as defined on the im
    |
 LL | impl<'a> FromTuple<'a> for C<'a> {
    |      ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/type-alias-free-regions.rs:27:9
    |
 LL |         C { f: Box::new(b.0) }
index e38b77fdcea012dd5b719a33c1222c933ca402f3..253e382511045c4163c152317501755de690b2bd 100644 (file)
@@ -5,7 +5,7 @@ LL |     SomeEnum::SomeVariant::<&'static u32> { t: &c };
    |                                                ^^
    |                                                |
    |                                                borrowed value does not live long enough
-   |                                                requires that `c` is borrowed for `'static`
+   |                                                this usage requires that `c` is borrowed for `'static`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -19,7 +19,7 @@ LL |     SomeEnum::SomeVariant::<&'a u32> { t: &c };
    |                                           ^^
    |                                           |
    |                                           borrowed value does not live long enough
-   |                                           requires that `c` is borrowed for `'a`
+   |                                           this usage requires that `c` is borrowed for `'a`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -33,7 +33,7 @@ LL |         SomeEnum::SomeVariant::<&'a u32> { t: &c };
    |                                               ^^
    |                                               |
    |                                               borrowed value does not live long enough
-   |                                               requires that `c` is borrowed for `'a`
+   |                                               this usage requires that `c` is borrowed for `'a`
 LL |     };
    |     - `c` dropped here while still borrowed
 
index 3c3003477c2d6e688fb47d0a0c8e9e9eab664f0e..8b9d1705df6ad816de949a8b3436d1c93e4bc8a3 100644 (file)
@@ -5,7 +5,7 @@ LL |     SomeStruct::<&'static u32> { t: &c };
    |                                     ^^
    |                                     |
    |                                     borrowed value does not live long enough
-   |                                     requires that `c` is borrowed for `'static`
+   |                                     this usage requires that `c` is borrowed for `'static`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -19,7 +19,7 @@ LL |     SomeStruct::<&'a u32> { t: &c };
    |                                ^^
    |                                |
    |                                borrowed value does not live long enough
-   |                                requires that `c` is borrowed for `'a`
+   |                                this usage requires that `c` is borrowed for `'a`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -33,7 +33,7 @@ LL |         SomeStruct::<&'a u32> { t: &c };
    |                                    ^^
    |                                    |
    |                                    borrowed value does not live long enough
-   |                                    requires that `c` is borrowed for `'a`
+   |                                    this usage requires that `c` is borrowed for `'a`
 LL |     };
    |     - `c` dropped here while still borrowed
 
index 810912bf886187a3b9fb2b6ec7670ed9a5449fb1..2fa7042631d21dd924429e47978eebc11b9c1196 100644 (file)
@@ -5,7 +5,7 @@ LL |     SomeEnum::SomeVariant::<&'static u32>(&c);
    |                                           ^^
    |                                           |
    |                                           borrowed value does not live long enough
-   |                                           requires that `c` is borrowed for `'static`
+   |                                           this usage requires that `c` is borrowed for `'static`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -19,7 +19,7 @@ LL |     SomeEnum::SomeVariant::<&'a u32>(&c);
    |                                      ^^
    |                                      |
    |                                      borrowed value does not live long enough
-   |                                      requires that `c` is borrowed for `'a`
+   |                                      this usage requires that `c` is borrowed for `'a`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -33,7 +33,7 @@ LL |         SomeEnum::SomeVariant::<&'a u32>(&c);
    |                                          ^^
    |                                          |
    |                                          borrowed value does not live long enough
-   |                                          requires that `c` is borrowed for `'a`
+   |                                          this usage requires that `c` is borrowed for `'a`
 LL |     };
    |     - `c` dropped here while still borrowed
 
index 4d2140eca1b02a87c239ba64ed0d92607fb3fe91..76b5252258c7bc3260014944e20b50387cb4291f 100644 (file)
@@ -5,7 +5,7 @@ LL |     SomeStruct::<&'static u32>(&c);
    |                                ^^
    |                                |
    |                                borrowed value does not live long enough
-   |                                requires that `c` is borrowed for `'static`
+   |                                this usage requires that `c` is borrowed for `'static`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -19,7 +19,7 @@ LL |     SomeStruct::<&'a u32>(&c);
    |                           ^^
    |                           |
    |                           borrowed value does not live long enough
-   |                           requires that `c` is borrowed for `'a`
+   |                           this usage requires that `c` is borrowed for `'a`
 LL | }
    | - `c` dropped here while still borrowed
 
@@ -33,7 +33,7 @@ LL |         SomeStruct::<&'a u32>(&c);
    |                               ^^
    |                               |
    |                               borrowed value does not live long enough
-   |                               requires that `c` is borrowed for `'a`
+   |                               this usage requires that `c` is borrowed for `'a`
 LL |     };
    |     - `c` dropped here while still borrowed
 
index 2e990131e61de810b0041a90eda6d707e358c5b2..8499b00f6f5567b81d76b1050b468418414b3624 100644 (file)
@@ -6,7 +6,7 @@ LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
    |        |
    |        lifetime `'a` defined here
 LL |     Foo { x, y };
-   |           ^ requires that `'a` must outlive `'b`
+   |           ^ this usage requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
 
index f8be5e76f7a1443b80c06c9f0bfac754ae1d3b5b..ce25da559da3faef9fd6e4d90f6c95722aa8c7c0 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
   --> $DIR/no_send-rc.rs:7:9
    |
 LL |     bar(x);
-   |         ^ `Rc<{integer}>` cannot be sent between threads safely
+   |     --- ^ `Rc<{integer}>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Rc<{integer}>`
 note: required by a bound in `bar`
index 2f8cf3569aeeed5c286d4f6bbe62bfcb26e62611..ee7bdf282b740122a7cb3a194c56c03c81518479 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be sent between threads safely
   --> $DIR/no_send-struct.rs:15:9
    |
 LL |     bar(x);
-   |         ^ `Foo` cannot be sent between threads safely
+   |     --- ^ `Foo` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Foo`
 note: required by a bound in `bar`
index 8983b0867898ad6e348889933b5dd25ab95107c1..9ce3a318f1d3ba22e2329c9dd621c6339297c601 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be shared between threads safely
   --> $DIR/no_share-struct.rs:12:9
    |
 LL |     bar(x);
-   |         ^ `Foo` cannot be shared between threads safely
+   |     --- ^ `Foo` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Foo`
 note: required by a bound in `bar`
index 6732391e1a1fbda8e09a2b177c55ca3300096203..4e4bcdf234dcf0eadbbb16d14338085ac5c21f38 100644 (file)
@@ -7,7 +7,7 @@ LL | const C: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL | const C: i32 = 1i32;
-   |                ~~~~
+   |                 ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:2:15
@@ -26,7 +26,7 @@ LL |     let c: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     let c: i32 = 1i32;
-   |                  ~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:6:17
@@ -47,7 +47,7 @@ LL |     let c: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     let c: i32 = 1i32;
-   |                  ~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:11:17
@@ -60,7 +60,7 @@ LL |     let d: i8 = c;
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     let d: i8 = c.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~
+   |                  ++++++++++++++++++++
 
 error: aborting due to 6 previous errors
 
index 9a3248c5720dbf0f6dc5dd7eb4ac7e13aa99257d..6319c1ead24eec010e171885528287437653288b 100644 (file)
@@ -7,7 +7,7 @@ LL |     test(array.len());
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     test(array.len().try_into().unwrap());
-   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error: aborting due to previous error
 
index 83d8ce5eea9ac57a98f120ec225cd86872ca95fb..a7b342739aa1b425a71396c5437ffcaee73a38c5 100644 (file)
@@ -9,27 +9,33 @@ LL |     let x: u16 = foo();
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     let x: u16 = foo().try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-2.rs:7:18
    |
 LL |     let y: i64 = x + x;
-   |            ---   ^^^^^
-   |            |     |
-   |            |     expected `i64`, found `u16`
-   |            |     help: you can convert a `u16` to an `i64`: `(x + x).into()`
+   |            ---   ^^^^^ expected `i64`, found `u16`
+   |            |
    |            expected due to this
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |     let y: i64 = (x + x).into();
+   |                  +     ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-2.rs:9:18
    |
 LL |     let z: i32 = x + x;
-   |            ---   ^^^^^
-   |            |     |
-   |            |     expected `i32`, found `u16`
-   |            |     help: you can convert a `u16` to an `i32`: `(x + x).into()`
+   |            ---   ^^^^^ expected `i32`, found `u16`
+   |            |
    |            expected due to this
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |     let z: i32 = (x + x).into();
+   |                  +     ++++++++
 
 error: aborting due to 3 previous errors
 
index b0ff50748fef1bd4e380dcf3a92690c410a9360b..2f58f164985db92b3fd4f5b8c2b8802c4c902c65 100644 (file)
@@ -7,7 +7,7 @@ LL |         x_u8 > x_u16;
 help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
    |
 LL |         u16::from(x_u8) > x_u16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:25:16
@@ -18,7 +18,7 @@ LL |         x_u8 > x_u32;
 help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
    |
 LL |         u32::from(x_u8) > x_u32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:27:16
@@ -29,7 +29,7 @@ LL |         x_u8 > x_u64;
 help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u8) > x_u64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:29:16
@@ -40,7 +40,7 @@ LL |         x_u8 > x_u128;
 help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u8) > x_u128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:31:16
@@ -51,16 +51,18 @@ LL |         x_u8 > x_usize;
 help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
    |
 LL |         usize::from(x_u8) > x_usize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:34:17
    |
 LL |         x_u16 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u16`, found `u8`
-   |                 help: you can convert a `u8` to a `u16`: `x_u8.into()`
+   |                 ^^^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |         x_u16 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:36:17
@@ -71,7 +73,7 @@ LL |         x_u16 > x_u32;
 help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
    |
 LL |         u32::from(x_u16) > x_u32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:38:17
@@ -82,7 +84,7 @@ LL |         x_u16 > x_u64;
 help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u16) > x_u64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:40:17
@@ -93,7 +95,7 @@ LL |         x_u16 > x_u128;
 help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u16) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:42:17
@@ -104,25 +106,29 @@ LL |         x_u16 > x_usize;
 help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
    |
 LL |         usize::from(x_u16) > x_usize;
-   |         ~~~~~~~~~~~~~~~~~~
+   |         ++++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:45:17
    |
 LL |         x_u32 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u32`, found `u8`
-   |                 help: you can convert a `u8` to a `u32`: `x_u8.into()`
+   |                 ^^^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |         x_u32 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:47:17
    |
 LL |         x_u32 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u32`, found `u16`
-   |                 help: you can convert a `u16` to a `u32`: `x_u16.into()`
+   |                 ^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |         x_u32 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:49:17
@@ -133,7 +139,7 @@ LL |         x_u32 > x_u64;
 help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u32) > x_u64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:51:17
@@ -144,7 +150,7 @@ LL |         x_u32 > x_u128;
 help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u32) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:53:17
@@ -155,34 +161,40 @@ LL |         x_u32 > x_usize;
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:56:17
    |
 LL |         x_u64 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u64`, found `u8`
-   |                 help: you can convert a `u8` to a `u64`: `x_u8.into()`
+   |                 ^^^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |         x_u64 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:58:17
    |
 LL |         x_u64 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u64`, found `u16`
-   |                 help: you can convert a `u16` to a `u64`: `x_u16.into()`
+   |                 ^^^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |         x_u64 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:60:17
    |
 LL |         x_u64 > x_u32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u64`, found `u32`
-   |                 help: you can convert a `u32` to a `u64`: `x_u32.into()`
+   |                 ^^^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |         x_u64 > x_u32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:62:17
@@ -193,7 +205,7 @@ LL |         x_u64 > x_u128;
 help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u64) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:64:17
@@ -204,43 +216,51 @@ LL |         x_u64 > x_usize;
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:67:18
    |
 LL |         x_u128 > x_u8;
-   |                  ^^^^
-   |                  |
-   |                  expected `u128`, found `u8`
-   |                  help: you can convert a `u8` to a `u128`: `x_u8.into()`
+   |                  ^^^^ expected `u128`, found `u8`
+   |
+help: you can convert a `u8` to a `u128`
+   |
+LL |         x_u128 > x_u8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:69:18
    |
 LL |         x_u128 > x_u16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u16`
-   |                  help: you can convert a `u16` to a `u128`: `x_u16.into()`
+   |                  ^^^^^ expected `u128`, found `u16`
+   |
+help: you can convert a `u16` to a `u128`
+   |
+LL |         x_u128 > x_u16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:71:18
    |
 LL |         x_u128 > x_u32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u32`
-   |                  help: you can convert a `u32` to a `u128`: `x_u32.into()`
+   |                  ^^^^^ expected `u128`, found `u32`
+   |
+help: you can convert a `u32` to a `u128`
+   |
+LL |         x_u128 > x_u32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:73:18
    |
 LL |         x_u128 > x_u64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u64`
-   |                  help: you can convert a `u64` to a `u128`: `x_u64.into()`
+   |                  ^^^^^ expected `u128`, found `u64`
+   |
+help: you can convert a `u64` to a `u128`
+   |
+LL |         x_u128 > x_u64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:75:18
@@ -251,25 +271,29 @@ LL |         x_u128 > x_usize;
 help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_usize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:78:19
    |
 LL |         x_usize > x_u8;
-   |                   ^^^^
-   |                   |
-   |                   expected `usize`, found `u8`
-   |                   help: you can convert a `u8` to a `usize`: `x_u8.into()`
+   |                   ^^^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |         x_usize > x_u8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:80:19
    |
 LL |         x_usize > x_u16;
-   |                   ^^^^^
-   |                   |
-   |                   expected `usize`, found `u16`
-   |                   help: you can convert a `u16` to a `usize`: `x_u16.into()`
+   |                   ^^^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |         x_usize > x_u16.into();
+   |                        +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:82:19
@@ -280,7 +304,7 @@ LL |         x_usize > x_u32;
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:84:19
@@ -291,7 +315,7 @@ LL |         x_usize > x_u64;
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:86:19
@@ -302,7 +326,7 @@ LL |         x_usize > x_u128;
 help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:92:16
@@ -313,7 +337,7 @@ LL |         x_i8 > x_i16;
 help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
    |
 LL |         i16::from(x_i8) > x_i16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:94:16
@@ -324,7 +348,7 @@ LL |         x_i8 > x_i32;
 help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_i8) > x_i32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:96:16
@@ -335,7 +359,7 @@ LL |         x_i8 > x_i64;
 help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i8) > x_i64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:98:16
@@ -346,7 +370,7 @@ LL |         x_i8 > x_i128;
 help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i8) > x_i128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:100:16
@@ -357,16 +381,18 @@ LL |         x_i8 > x_isize;
 help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_i8) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:103:17
    |
 LL |         x_i16 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i16`, found `i8`
-   |                 help: you can convert an `i8` to an `i16`: `x_i8.into()`
+   |                 ^^^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |         x_i16 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:105:17
@@ -377,7 +403,7 @@ LL |         x_i16 > x_i32;
 help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_i16) > x_i32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:107:17
@@ -388,7 +414,7 @@ LL |         x_i16 > x_i64;
 help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i16) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:109:17
@@ -399,7 +425,7 @@ LL |         x_i16 > x_i128;
 help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i16) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:111:17
@@ -410,25 +436,29 @@ LL |         x_i16 > x_isize;
 help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_i16) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~~
+   |         ++++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:114:17
    |
 LL |         x_i32 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i32`, found `i8`
-   |                 help: you can convert an `i8` to an `i32`: `x_i8.into()`
+   |                 ^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |         x_i32 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:116:17
    |
 LL |         x_i32 > x_i16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i32`, found `i16`
-   |                 help: you can convert an `i16` to an `i32`: `x_i16.into()`
+   |                 ^^^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |         x_i32 > x_i16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:118:17
@@ -439,7 +469,7 @@ LL |         x_i32 > x_i64;
 help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i32) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:120:17
@@ -450,7 +480,7 @@ LL |         x_i32 > x_i128;
 help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i32) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:122:17
@@ -461,34 +491,40 @@ LL |         x_i32 > x_isize;
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:125:17
    |
 LL |         x_i64 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i64`, found `i8`
-   |                 help: you can convert an `i8` to an `i64`: `x_i8.into()`
+   |                 ^^^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |         x_i64 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:127:17
    |
 LL |         x_i64 > x_i16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `i16`
-   |                 help: you can convert an `i16` to an `i64`: `x_i16.into()`
+   |                 ^^^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |         x_i64 > x_i16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:129:17
    |
 LL |         x_i64 > x_i32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `i32`
-   |                 help: you can convert an `i32` to an `i64`: `x_i32.into()`
+   |                 ^^^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |         x_i64 > x_i32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:131:17
@@ -499,7 +535,7 @@ LL |         x_i64 > x_i128;
 help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i64) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:133:17
@@ -510,43 +546,51 @@ LL |         x_i64 > x_isize;
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:136:18
    |
 LL |         x_i128 > x_i8;
-   |                  ^^^^
-   |                  |
-   |                  expected `i128`, found `i8`
-   |                  help: you can convert an `i8` to an `i128`: `x_i8.into()`
+   |                  ^^^^ expected `i128`, found `i8`
+   |
+help: you can convert an `i8` to an `i128`
+   |
+LL |         x_i128 > x_i8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:138:18
    |
 LL |         x_i128 > x_i16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i16`
-   |                  help: you can convert an `i16` to an `i128`: `x_i16.into()`
+   |                  ^^^^^ expected `i128`, found `i16`
+   |
+help: you can convert an `i16` to an `i128`
+   |
+LL |         x_i128 > x_i16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:140:18
    |
 LL |         x_i128 > x_i32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i32`
-   |                  help: you can convert an `i32` to an `i128`: `x_i32.into()`
+   |                  ^^^^^ expected `i128`, found `i32`
+   |
+help: you can convert an `i32` to an `i128`
+   |
+LL |         x_i128 > x_i32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:142:18
    |
 LL |         x_i128 > x_i64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i64`
-   |                  help: you can convert an `i64` to an `i128`: `x_i64.into()`
+   |                  ^^^^^ expected `i128`, found `i64`
+   |
+help: you can convert an `i64` to an `i128`
+   |
+LL |         x_i128 > x_i64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:144:18
@@ -557,25 +601,29 @@ LL |         x_i128 > x_isize;
 help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_isize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:147:19
    |
 LL |         x_isize > x_i8;
-   |                   ^^^^
-   |                   |
-   |                   expected `isize`, found `i8`
-   |                   help: you can convert an `i8` to an `isize`: `x_i8.into()`
+   |                   ^^^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |         x_isize > x_i8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:149:19
    |
 LL |         x_isize > x_i16;
-   |                   ^^^^^
-   |                   |
-   |                   expected `isize`, found `i16`
-   |                   help: you can convert an `i16` to an `isize`: `x_i16.into()`
+   |                   ^^^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |         x_isize > x_i16.into();
+   |                        +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:151:19
@@ -586,7 +634,7 @@ LL |         x_isize > x_i32;
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:153:19
@@ -597,7 +645,7 @@ LL |         x_isize > x_i64;
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:155:19
@@ -608,7 +656,7 @@ LL |         x_isize > x_i128;
 help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:161:16
@@ -619,7 +667,7 @@ LL |         x_u8 > x_i8;
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
 LL |         x_u8 > x_i8.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:163:16
@@ -630,7 +678,7 @@ LL |         x_u8 > x_i16;
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
    |
 LL |         i16::from(x_u8) > x_i16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:165:16
@@ -641,7 +689,7 @@ LL |         x_u8 > x_i32;
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_u8) > x_i32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:167:16
@@ -652,7 +700,7 @@ LL |         x_u8 > x_i64;
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u8) > x_i64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:169:16
@@ -663,7 +711,7 @@ LL |         x_u8 > x_i128;
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u8) > x_i128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:171:16
@@ -674,7 +722,7 @@ LL |         x_u8 > x_isize;
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_u8) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:174:17
@@ -685,7 +733,7 @@ LL |         x_u16 > x_i8;
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:176:17
@@ -696,7 +744,7 @@ LL |         x_u16 > x_i16;
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:178:17
@@ -707,7 +755,7 @@ LL |         x_u16 > x_i32;
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_u16) > x_i32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:180:17
@@ -718,7 +766,7 @@ LL |         x_u16 > x_i64;
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u16) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:182:17
@@ -729,7 +777,7 @@ LL |         x_u16 > x_i128;
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u16) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:184:17
@@ -740,7 +788,7 @@ LL |         x_u16 > x_isize;
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:187:17
@@ -751,7 +799,7 @@ LL |         x_u32 > x_i8;
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:189:17
@@ -762,7 +810,7 @@ LL |         x_u32 > x_i16;
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:191:17
@@ -773,7 +821,7 @@ LL |         x_u32 > x_i32;
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:193:17
@@ -784,7 +832,7 @@ LL |         x_u32 > x_i64;
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u32) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:195:17
@@ -795,7 +843,7 @@ LL |         x_u32 > x_i128;
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u32) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:197:17
@@ -806,7 +854,7 @@ LL |         x_u32 > x_isize;
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:200:17
@@ -817,7 +865,7 @@ LL |         x_u64 > x_i8;
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:202:17
@@ -828,7 +876,7 @@ LL |         x_u64 > x_i16;
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:204:17
@@ -839,7 +887,7 @@ LL |         x_u64 > x_i32;
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:206:17
@@ -850,7 +898,7 @@ LL |         x_u64 > x_i64;
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:208:17
@@ -861,7 +909,7 @@ LL |         x_u64 > x_i128;
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u64) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:210:17
@@ -872,7 +920,7 @@ LL |         x_u64 > x_isize;
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:213:18
@@ -883,7 +931,7 @@ LL |         x_u128 > x_i8;
 help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i8.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:215:18
@@ -894,7 +942,7 @@ LL |         x_u128 > x_i16;
 help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i16.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:217:18
@@ -905,7 +953,7 @@ LL |         x_u128 > x_i32;
 help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i32.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:219:18
@@ -916,7 +964,7 @@ LL |         x_u128 > x_i64;
 help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i64.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:221:18
@@ -927,7 +975,7 @@ LL |         x_u128 > x_i128;
 help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i128.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:223:18
@@ -938,7 +986,7 @@ LL |         x_u128 > x_isize;
 help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_isize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:226:19
@@ -949,7 +997,7 @@ LL |         x_usize > x_i8;
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i8.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:228:19
@@ -960,7 +1008,7 @@ LL |         x_usize > x_i16;
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i16.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:230:19
@@ -971,7 +1019,7 @@ LL |         x_usize > x_i32;
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:232:19
@@ -982,7 +1030,7 @@ LL |         x_usize > x_i64;
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:234:19
@@ -993,7 +1041,7 @@ LL |         x_usize > x_i128;
 help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:236:19
@@ -1004,7 +1052,7 @@ LL |         x_usize > x_isize;
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_isize.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:242:16
@@ -1015,7 +1063,7 @@ LL |         x_i8 > x_u8;
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u8.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:244:16
@@ -1026,7 +1074,7 @@ LL |         x_i8 > x_u16;
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u16.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:246:16
@@ -1037,7 +1085,7 @@ LL |         x_i8 > x_u32;
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u32.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:248:16
@@ -1048,7 +1096,7 @@ LL |         x_i8 > x_u64;
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u64.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:250:16
@@ -1059,7 +1107,7 @@ LL |         x_i8 > x_u128;
 help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u128.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:252:16
@@ -1070,16 +1118,18 @@ LL |         x_i8 > x_usize;
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_usize.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:255:17
    |
 LL |         x_i16 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i16`, found `u8`
-   |                 help: you can convert a `u8` to an `i16`: `x_u8.into()`
+   |                 ^^^^ expected `i16`, found `u8`
+   |
+help: you can convert a `u8` to an `i16`
+   |
+LL |         x_i16 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:257:17
@@ -1090,7 +1140,7 @@ LL |         x_i16 > x_u16;
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:259:17
@@ -1101,7 +1151,7 @@ LL |         x_i16 > x_u32;
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:261:17
@@ -1112,7 +1162,7 @@ LL |         x_i16 > x_u64;
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:263:17
@@ -1123,7 +1173,7 @@ LL |         x_i16 > x_u128;
 help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:265:17
@@ -1134,25 +1184,29 @@ LL |         x_i16 > x_usize;
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:268:17
    |
 LL |         x_i32 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i32`, found `u8`
-   |                 help: you can convert a `u8` to an `i32`: `x_u8.into()`
+   |                 ^^^^ expected `i32`, found `u8`
+   |
+help: you can convert a `u8` to an `i32`
+   |
+LL |         x_i32 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:270:17
    |
 LL |         x_i32 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i32`, found `u16`
-   |                 help: you can convert a `u16` to an `i32`: `x_u16.into()`
+   |                 ^^^^^ expected `i32`, found `u16`
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |         x_i32 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:272:17
@@ -1163,7 +1217,7 @@ LL |         x_i32 > x_u32;
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:274:17
@@ -1174,7 +1228,7 @@ LL |         x_i32 > x_u64;
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:276:17
@@ -1185,7 +1239,7 @@ LL |         x_i32 > x_u128;
 help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:278:17
@@ -1196,34 +1250,40 @@ LL |         x_i32 > x_usize;
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:281:17
    |
 LL |         x_i64 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i64`, found `u8`
-   |                 help: you can convert a `u8` to an `i64`: `x_u8.into()`
+   |                 ^^^^ expected `i64`, found `u8`
+   |
+help: you can convert a `u8` to an `i64`
+   |
+LL |         x_i64 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:283:17
    |
 LL |         x_i64 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `u16`
-   |                 help: you can convert a `u16` to an `i64`: `x_u16.into()`
+   |                 ^^^^^ expected `i64`, found `u16`
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |         x_i64 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:285:17
    |
 LL |         x_i64 > x_u32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `u32`
-   |                 help: you can convert a `u32` to an `i64`: `x_u32.into()`
+   |                 ^^^^^ expected `i64`, found `u32`
+   |
+help: you can convert a `u32` to an `i64`
+   |
+LL |         x_i64 > x_u32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:287:17
@@ -1234,7 +1294,7 @@ LL |         x_i64 > x_u64;
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:289:17
@@ -1245,7 +1305,7 @@ LL |         x_i64 > x_u128;
 help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:291:17
@@ -1256,43 +1316,51 @@ LL |         x_i64 > x_usize;
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:294:18
    |
 LL |         x_i128 > x_u8;
-   |                  ^^^^
-   |                  |
-   |                  expected `i128`, found `u8`
-   |                  help: you can convert a `u8` to an `i128`: `x_u8.into()`
+   |                  ^^^^ expected `i128`, found `u8`
+   |
+help: you can convert a `u8` to an `i128`
+   |
+LL |         x_i128 > x_u8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:296:18
    |
 LL |         x_i128 > x_u16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u16`
-   |                  help: you can convert a `u16` to an `i128`: `x_u16.into()`
+   |                  ^^^^^ expected `i128`, found `u16`
+   |
+help: you can convert a `u16` to an `i128`
+   |
+LL |         x_i128 > x_u16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:298:18
    |
 LL |         x_i128 > x_u32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u32`
-   |                  help: you can convert a `u32` to an `i128`: `x_u32.into()`
+   |                  ^^^^^ expected `i128`, found `u32`
+   |
+help: you can convert a `u32` to an `i128`
+   |
+LL |         x_i128 > x_u32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:300:18
    |
 LL |         x_i128 > x_u64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u64`
-   |                  help: you can convert a `u64` to an `i128`: `x_u64.into()`
+   |                  ^^^^^ expected `i128`, found `u64`
+   |
+help: you can convert a `u64` to an `i128`
+   |
+LL |         x_i128 > x_u64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:302:18
@@ -1303,7 +1371,7 @@ LL |         x_i128 > x_u128;
 help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_u128.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:304:18
@@ -1314,16 +1382,18 @@ LL |         x_i128 > x_usize;
 help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_usize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:307:19
    |
 LL |         x_isize > x_u8;
-   |                   ^^^^
-   |                   |
-   |                   expected `isize`, found `u8`
-   |                   help: you can convert a `u8` to an `isize`: `x_u8.into()`
+   |                   ^^^^ expected `isize`, found `u8`
+   |
+help: you can convert a `u8` to an `isize`
+   |
+LL |         x_isize > x_u8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:309:19
@@ -1334,7 +1404,7 @@ LL |         x_isize > x_u16;
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u16.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:311:19
@@ -1345,7 +1415,7 @@ LL |         x_isize > x_u32;
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:313:19
@@ -1356,7 +1426,7 @@ LL |         x_isize > x_u64;
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:315:19
@@ -1367,7 +1437,7 @@ LL |         x_isize > x_u128;
 help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:317:19
@@ -1378,7 +1448,7 @@ LL |         x_isize > x_usize;
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_usize.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
 error: aborting due to 132 previous errors
 
index 4510ce10b3dc48b475d04342334128b98055d75a..e4843206de1dd48c2025a796c22552b2f612a79a 100644 (file)
@@ -47,7 +47,7 @@ LL |     x_u8 > -1_isize;
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
    |
 LL |     isize::from(x_u8) > -1_isize;
-   |     ~~~~~~~~~~~~~~~~~
+   |     ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:23:15
@@ -74,7 +74,7 @@ LL |     x_u64 > -1_i128;
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u64) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:29:13
@@ -85,7 +85,7 @@ LL |     x_u32 > -1_i128;
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u32) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:31:13
@@ -96,7 +96,7 @@ LL |     x_u16 > -1_i128;
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u16) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:33:12
@@ -107,7 +107,7 @@ LL |     x_u8 > -1_i128;
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u8) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~
+   |     +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:36:15
@@ -142,7 +142,7 @@ LL |     x_u32 > -1_i64;
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u32) > -1_i64;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:44:13
@@ -153,7 +153,7 @@ LL |     x_u16 > -1_i64;
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u16) > -1_i64;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:46:12
@@ -164,7 +164,7 @@ LL |     x_u8 > -1_i64;
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u8) > -1_i64;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:49:15
@@ -207,7 +207,7 @@ LL |     x_u16 > -1_i32;
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
    |
 LL |     i32::from(x_u16) > -1_i32;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:59:12
@@ -218,7 +218,7 @@ LL |     x_u8 > -1_i32;
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
    |
 LL |     i32::from(x_u8) > -1_i32;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:62:15
@@ -269,7 +269,7 @@ LL |     x_u8 > -1_i16;
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
    |
 LL |     i16::from(x_u8) > -1_i16;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:75:15
index 8bc617be57313a6c42aacf72ac6db687f6f4567e..3e2bc5bc82d4206f76e9246e0d5c51cec6b8da5c 100644 (file)
@@ -7,7 +7,7 @@ LL |     foo::<usize>(x_u64);
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_u64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:25:18
@@ -18,25 +18,29 @@ LL |     foo::<usize>(x_u32);
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_u32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:27:18
    |
 LL |     foo::<usize>(x_u16);
-   |                  ^^^^^
-   |                  |
-   |                  expected `usize`, found `u16`
-   |                  help: you can convert a `u16` to a `usize`: `x_u16.into()`
+   |                  ^^^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |     foo::<usize>(x_u16.into());
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:29:18
    |
 LL |     foo::<usize>(x_u8);
-   |                  ^^^^
-   |                  |
-   |                  expected `usize`, found `u8`
-   |                  help: you can convert a `u8` to a `usize`: `x_u8.into()`
+   |                  ^^^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |     foo::<usize>(x_u8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:31:18
@@ -47,7 +51,7 @@ LL |     foo::<usize>(x_isize);
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_isize.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:33:18
@@ -58,7 +62,7 @@ LL |     foo::<usize>(x_i64);
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:35:18
@@ -69,7 +73,7 @@ LL |     foo::<usize>(x_i32);
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:37:18
@@ -80,7 +84,7 @@ LL |     foo::<usize>(x_i16);
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i16.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:39:18
@@ -91,7 +95,7 @@ LL |     foo::<usize>(x_i8);
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i8.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:44:18
@@ -102,7 +106,7 @@ LL |     foo::<isize>(x_usize);
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_usize.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:46:18
@@ -113,7 +117,7 @@ LL |     foo::<isize>(x_u64);
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:48:18
@@ -124,7 +128,7 @@ LL |     foo::<isize>(x_u32);
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:50:18
@@ -135,16 +139,18 @@ LL |     foo::<isize>(x_u16);
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u16.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:52:18
    |
 LL |     foo::<isize>(x_u8);
-   |                  ^^^^
-   |                  |
-   |                  expected `isize`, found `u8`
-   |                  help: you can convert a `u8` to an `isize`: `x_u8.into()`
+   |                  ^^^^ expected `isize`, found `u8`
+   |
+help: you can convert a `u8` to an `isize`
+   |
+LL |     foo::<isize>(x_u8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:55:18
@@ -155,7 +161,7 @@ LL |     foo::<isize>(x_i64);
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_i64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:57:18
@@ -166,25 +172,29 @@ LL |     foo::<isize>(x_i32);
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_i32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:59:18
    |
 LL |     foo::<isize>(x_i16);
-   |                  ^^^^^
-   |                  |
-   |                  expected `isize`, found `i16`
-   |                  help: you can convert an `i16` to an `isize`: `x_i16.into()`
+   |                  ^^^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |     foo::<isize>(x_i16.into());
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:61:18
    |
 LL |     foo::<isize>(x_i8);
-   |                  ^^^^
-   |                  |
-   |                  expected `isize`, found `i8`
-   |                  help: you can convert an `i8` to an `isize`: `x_i8.into()`
+   |                  ^^^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |     foo::<isize>(x_i8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:66:16
@@ -195,34 +205,40 @@ LL |     foo::<u64>(x_usize);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:69:16
    |
 LL |     foo::<u64>(x_u32);
-   |                ^^^^^
-   |                |
-   |                expected `u64`, found `u32`
-   |                help: you can convert a `u32` to a `u64`: `x_u32.into()`
+   |                ^^^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |     foo::<u64>(x_u32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:71:16
    |
 LL |     foo::<u64>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `u64`, found `u16`
-   |                help: you can convert a `u16` to a `u64`: `x_u16.into()`
+   |                ^^^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |     foo::<u64>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:73:16
    |
 LL |     foo::<u64>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u64`, found `u8`
-   |                help: you can convert a `u8` to a `u64`: `x_u8.into()`
+   |                ^^^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |     foo::<u64>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:75:16
@@ -233,7 +249,7 @@ LL |     foo::<u64>(x_isize);
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:77:16
@@ -244,7 +260,7 @@ LL |     foo::<u64>(x_i64);
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:79:16
@@ -255,7 +271,7 @@ LL |     foo::<u64>(x_i32);
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:81:16
@@ -266,7 +282,7 @@ LL |     foo::<u64>(x_i16);
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:83:16
@@ -277,7 +293,7 @@ LL |     foo::<u64>(x_i8);
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:88:16
@@ -288,7 +304,7 @@ LL |     foo::<i64>(x_usize);
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:90:16
@@ -299,34 +315,40 @@ LL |     foo::<i64>(x_u64);
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:92:16
    |
 LL |     foo::<i64>(x_u32);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `u32`
-   |                help: you can convert a `u32` to an `i64`: `x_u32.into()`
+   |                ^^^^^ expected `i64`, found `u32`
+   |
+help: you can convert a `u32` to an `i64`
+   |
+LL |     foo::<i64>(x_u32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:94:16
    |
 LL |     foo::<i64>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `u16`
-   |                help: you can convert a `u16` to an `i64`: `x_u16.into()`
+   |                ^^^^^ expected `i64`, found `u16`
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |     foo::<i64>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:96:16
    |
 LL |     foo::<i64>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i64`, found `u8`
-   |                help: you can convert a `u8` to an `i64`: `x_u8.into()`
+   |                ^^^^ expected `i64`, found `u8`
+   |
+help: you can convert a `u8` to an `i64`
+   |
+LL |     foo::<i64>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:98:16
@@ -337,34 +359,40 @@ LL |     foo::<i64>(x_isize);
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:101:16
    |
 LL |     foo::<i64>(x_i32);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `i32`
-   |                help: you can convert an `i32` to an `i64`: `x_i32.into()`
+   |                ^^^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     foo::<i64>(x_i32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:103:16
    |
 LL |     foo::<i64>(x_i16);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `i16`
-   |                help: you can convert an `i16` to an `i64`: `x_i16.into()`
+   |                ^^^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     foo::<i64>(x_i16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:105:16
    |
 LL |     foo::<i64>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i64`, found `i8`
-   |                help: you can convert an `i8` to an `i64`: `x_i8.into()`
+   |                ^^^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     foo::<i64>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:110:16
@@ -375,7 +403,7 @@ LL |     foo::<u32>(x_usize);
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:112:16
@@ -386,25 +414,29 @@ LL |     foo::<u32>(x_u64);
 help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:115:16
    |
 LL |     foo::<u32>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `x_u16.into()`
+   |                ^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:117:16
    |
 LL |     foo::<u32>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u32`, found `u8`
-   |                help: you can convert a `u8` to a `u32`: `x_u8.into()`
+   |                ^^^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |     foo::<u32>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:119:16
@@ -415,7 +447,7 @@ LL |     foo::<u32>(x_isize);
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:121:16
@@ -426,7 +458,7 @@ LL |     foo::<u32>(x_i64);
 help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:123:16
@@ -437,7 +469,7 @@ LL |     foo::<u32>(x_i32);
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:125:16
@@ -448,7 +480,7 @@ LL |     foo::<u32>(x_i16);
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:127:16
@@ -459,7 +491,7 @@ LL |     foo::<u32>(x_i8);
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:132:16
@@ -470,7 +502,7 @@ LL |     foo::<i32>(x_usize);
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:134:16
@@ -481,7 +513,7 @@ LL |     foo::<i32>(x_u64);
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:136:16
@@ -492,25 +524,29 @@ LL |     foo::<i32>(x_u32);
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:138:16
    |
 LL |     foo::<i32>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `u16`
-   |                help: you can convert a `u16` to an `i32`: `x_u16.into()`
+   |                ^^^^^ expected `i32`, found `u16`
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |     foo::<i32>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:140:16
    |
 LL |     foo::<i32>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i32`, found `u8`
-   |                help: you can convert a `u8` to an `i32`: `x_u8.into()`
+   |                ^^^^ expected `i32`, found `u8`
+   |
+help: you can convert a `u8` to an `i32`
+   |
+LL |     foo::<i32>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:142:16
@@ -521,7 +557,7 @@ LL |     foo::<i32>(x_isize);
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:144:16
@@ -532,25 +568,29 @@ LL |     foo::<i32>(x_i64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:147:16
    |
 LL |     foo::<i32>(x_i16);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `i16`
-   |                help: you can convert an `i16` to an `i32`: `x_i16.into()`
+   |                ^^^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     foo::<i32>(x_i16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:149:16
    |
 LL |     foo::<i32>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `x_i8.into()`
+   |                ^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:154:16
@@ -561,7 +601,7 @@ LL |     foo::<u16>(x_usize);
 help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:156:16
@@ -572,7 +612,7 @@ LL |     foo::<u16>(x_u64);
 help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:158:16
@@ -583,16 +623,18 @@ LL |     foo::<u16>(x_u32);
 help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:161:16
    |
 LL |     foo::<u16>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u16`, found `u8`
-   |                help: you can convert a `u8` to a `u16`: `x_u8.into()`
+   |                ^^^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     foo::<u16>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:163:16
@@ -603,7 +645,7 @@ LL |     foo::<u16>(x_isize);
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:165:16
@@ -614,7 +656,7 @@ LL |     foo::<u16>(x_i64);
 help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:167:16
@@ -625,7 +667,7 @@ LL |     foo::<u16>(x_i32);
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:169:16
@@ -636,7 +678,7 @@ LL |     foo::<u16>(x_i16);
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:171:16
@@ -647,7 +689,7 @@ LL |     foo::<u16>(x_i8);
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:176:16
@@ -658,7 +700,7 @@ LL |     foo::<i16>(x_usize);
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:178:16
@@ -669,7 +711,7 @@ LL |     foo::<i16>(x_u64);
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:180:16
@@ -680,7 +722,7 @@ LL |     foo::<i16>(x_u32);
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:182:16
@@ -691,16 +733,18 @@ LL |     foo::<i16>(x_u16);
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:184:16
    |
 LL |     foo::<i16>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i16`, found `u8`
-   |                help: you can convert a `u8` to an `i16`: `x_u8.into()`
+   |                ^^^^ expected `i16`, found `u8`
+   |
+help: you can convert a `u8` to an `i16`
+   |
+LL |     foo::<i16>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:186:16
@@ -711,7 +755,7 @@ LL |     foo::<i16>(x_isize);
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:188:16
@@ -722,7 +766,7 @@ LL |     foo::<i16>(x_i64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:190:16
@@ -733,16 +777,18 @@ LL |     foo::<i16>(x_i32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:193:16
    |
 LL |     foo::<i16>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i16`, found `i8`
-   |                help: you can convert an `i8` to an `i16`: `x_i8.into()`
+   |                ^^^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     foo::<i16>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:198:15
@@ -753,7 +799,7 @@ LL |     foo::<u8>(x_usize);
 help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_usize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:200:15
@@ -764,7 +810,7 @@ LL |     foo::<u8>(x_u64);
 help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:202:15
@@ -775,7 +821,7 @@ LL |     foo::<u8>(x_u32);
 help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:204:15
@@ -786,7 +832,7 @@ LL |     foo::<u8>(x_u16);
 help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:207:15
@@ -797,7 +843,7 @@ LL |     foo::<u8>(x_isize);
 help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_isize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:209:15
@@ -808,7 +854,7 @@ LL |     foo::<u8>(x_i64);
 help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:211:15
@@ -819,7 +865,7 @@ LL |     foo::<u8>(x_i32);
 help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:213:15
@@ -830,7 +876,7 @@ LL |     foo::<u8>(x_i16);
 help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:215:15
@@ -841,7 +887,7 @@ LL |     foo::<u8>(x_i8);
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i8.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:220:15
@@ -852,7 +898,7 @@ LL |     foo::<i8>(x_usize);
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_usize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:222:15
@@ -863,7 +909,7 @@ LL |     foo::<i8>(x_u64);
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:224:15
@@ -874,7 +920,7 @@ LL |     foo::<i8>(x_u32);
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:226:15
@@ -885,7 +931,7 @@ LL |     foo::<i8>(x_u16);
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:228:15
@@ -896,7 +942,7 @@ LL |     foo::<i8>(x_u8);
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u8.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:230:15
@@ -907,7 +953,7 @@ LL |     foo::<i8>(x_isize);
 help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_isize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:232:15
@@ -918,7 +964,7 @@ LL |     foo::<i8>(x_i64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:234:15
@@ -929,7 +975,7 @@ LL |     foo::<i8>(x_i32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:236:15
@@ -940,7 +986,7 @@ LL |     foo::<i8>(x_i16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:242:16
@@ -951,7 +997,7 @@ LL |     foo::<f64>(x_usize);
 help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f64>(x_usize as f64);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:244:16
@@ -962,7 +1008,7 @@ LL |     foo::<f64>(x_u64);
 help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f64>(x_u64 as f64);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:246:16
@@ -973,7 +1019,7 @@ LL |     foo::<f64>(x_u32);
 help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u32.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:248:16
@@ -984,7 +1030,7 @@ LL |     foo::<f64>(x_u16);
 help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:250:16
@@ -995,7 +1041,7 @@ LL |     foo::<f64>(x_u8);
 help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:252:16
@@ -1006,7 +1052,7 @@ LL |     foo::<f64>(x_isize);
 help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f64>(x_isize as f64);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:254:16
@@ -1017,7 +1063,7 @@ LL |     foo::<f64>(x_i64);
 help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f64>(x_i64 as f64);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:256:16
@@ -1028,7 +1074,7 @@ LL |     foo::<f64>(x_i32);
 help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i32.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:258:16
@@ -1039,7 +1085,7 @@ LL |     foo::<f64>(x_i16);
 help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:260:16
@@ -1050,16 +1096,18 @@ LL |     foo::<f64>(x_i8);
 help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:263:16
    |
 LL |     foo::<f64>(x_f32);
-   |                ^^^^^
-   |                |
-   |                expected `f64`, found `f32`
-   |                help: you can convert an `f32` to an `f64`: `x_f32.into()`
+   |                ^^^^^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     foo::<f64>(x_f32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:266:16
@@ -1070,7 +1118,7 @@ LL |     foo::<f32>(x_usize);
 help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_usize as f32);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:268:16
@@ -1081,7 +1129,7 @@ LL |     foo::<f32>(x_u64);
 help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_u64 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:270:16
@@ -1092,7 +1140,7 @@ LL |     foo::<f32>(x_u32);
 help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_u32 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:272:16
@@ -1103,7 +1151,7 @@ LL |     foo::<f32>(x_u16);
 help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:274:16
@@ -1114,7 +1162,7 @@ LL |     foo::<f32>(x_u8);
 help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:276:16
@@ -1125,7 +1173,7 @@ LL |     foo::<f32>(x_isize);
 help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_isize as f32);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:278:16
@@ -1136,7 +1184,7 @@ LL |     foo::<f32>(x_i64);
 help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_i64 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:280:16
@@ -1147,7 +1195,7 @@ LL |     foo::<f32>(x_i32);
 help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_i32 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:282:16
@@ -1158,7 +1206,7 @@ LL |     foo::<f32>(x_i16);
 help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:284:16
@@ -1169,25 +1217,29 @@ LL |     foo::<f32>(x_i8);
 help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:289:16
    |
 LL |     foo::<u32>(x_u8 as u16);
-   |                ^^^^^^^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `(x_u8 as u16).into()`
+   |                ^^^^^^^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>((x_u8 as u16).into());
+   |                +           ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:291:16
    |
 LL |     foo::<i32>(-x_i8);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `(-x_i8).into()`
+   |                ^^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>((-x_i8).into());
+   |                +     ++++++++
 
 error: aborting due to 113 previous errors
 
index b328fbe2cfb87a90c625b488bf7bb865bdb838b9..668405ed638c1d18ccbce364da0f940eb518fa36 100644 (file)
@@ -16,7 +16,10 @@ error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:7:17
    |
 LL |         S{0: a, 0x1: b, ..} => {}
-   |                 ^^^ struct `S` does not have this field
+   |                 ^^^
+   |                 |
+   |                 struct `S` does not have this field
+   |                 help: `S` has a field named `1`
 
 error: aborting due to 2 previous errors
 
index d3f02214e3b7a0f403c7ee6d35b3888e3defe6cf..b829946e522260f3e076bb0329cf9567b9fc9b2e 100644 (file)
@@ -7,7 +7,7 @@ LL |     foo::<usize>(42_u64);
 help: change the type of the numeric literal from `u64` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:9:18
@@ -18,7 +18,7 @@ LL |     foo::<usize>(42_u32);
 help: change the type of the numeric literal from `u32` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:11:18
@@ -29,7 +29,7 @@ LL |     foo::<usize>(42_u16);
 help: change the type of the numeric literal from `u16` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:13:18
@@ -40,7 +40,7 @@ LL |     foo::<usize>(42_u8);
 help: change the type of the numeric literal from `u8` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:15:18
@@ -51,7 +51,7 @@ LL |     foo::<usize>(42_isize);
 help: change the type of the numeric literal from `isize` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:17:18
@@ -62,7 +62,7 @@ LL |     foo::<usize>(42_i64);
 help: change the type of the numeric literal from `i64` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:19:18
@@ -73,7 +73,7 @@ LL |     foo::<usize>(42_i32);
 help: change the type of the numeric literal from `i32` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:21:18
@@ -84,7 +84,7 @@ LL |     foo::<usize>(42_i16);
 help: change the type of the numeric literal from `i16` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:23:18
@@ -95,7 +95,7 @@ LL |     foo::<usize>(42_i8);
 help: change the type of the numeric literal from `i8` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:25:18
@@ -106,7 +106,7 @@ LL |     foo::<usize>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `usize`
    |
 LL |     foo::<usize>(42usize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:27:18
@@ -117,7 +117,7 @@ LL |     foo::<usize>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `usize`
    |
 LL |     foo::<usize>(42usize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:30:18
@@ -128,7 +128,7 @@ LL |     foo::<isize>(42_usize);
 help: change the type of the numeric literal from `usize` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:32:18
@@ -139,7 +139,7 @@ LL |     foo::<isize>(42_u64);
 help: change the type of the numeric literal from `u64` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:34:18
@@ -150,7 +150,7 @@ LL |     foo::<isize>(42_u32);
 help: change the type of the numeric literal from `u32` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:36:18
@@ -161,7 +161,7 @@ LL |     foo::<isize>(42_u16);
 help: change the type of the numeric literal from `u16` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:38:18
@@ -172,7 +172,7 @@ LL |     foo::<isize>(42_u8);
 help: change the type of the numeric literal from `u8` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:41:18
@@ -183,7 +183,7 @@ LL |     foo::<isize>(42_i64);
 help: change the type of the numeric literal from `i64` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:43:18
@@ -194,7 +194,7 @@ LL |     foo::<isize>(42_i32);
 help: change the type of the numeric literal from `i32` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:45:18
@@ -205,7 +205,7 @@ LL |     foo::<isize>(42_i16);
 help: change the type of the numeric literal from `i16` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:47:18
@@ -216,7 +216,7 @@ LL |     foo::<isize>(42_i8);
 help: change the type of the numeric literal from `i8` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:49:18
@@ -227,7 +227,7 @@ LL |     foo::<isize>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `isize`
    |
 LL |     foo::<isize>(42isize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:51:18
@@ -238,7 +238,7 @@ LL |     foo::<isize>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `isize`
    |
 LL |     foo::<isize>(42isize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:54:16
@@ -249,7 +249,7 @@ LL |     foo::<u64>(42_usize);
 help: change the type of the numeric literal from `usize` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:57:16
@@ -260,7 +260,7 @@ LL |     foo::<u64>(42_u32);
 help: change the type of the numeric literal from `u32` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:59:16
@@ -271,7 +271,7 @@ LL |     foo::<u64>(42_u16);
 help: change the type of the numeric literal from `u16` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:61:16
@@ -282,7 +282,7 @@ LL |     foo::<u64>(42_u8);
 help: change the type of the numeric literal from `u8` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:63:16
@@ -293,7 +293,7 @@ LL |     foo::<u64>(42_isize);
 help: change the type of the numeric literal from `isize` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:65:16
@@ -304,7 +304,7 @@ LL |     foo::<u64>(42_i64);
 help: change the type of the numeric literal from `i64` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:67:16
@@ -315,7 +315,7 @@ LL |     foo::<u64>(42_i32);
 help: change the type of the numeric literal from `i32` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:69:16
@@ -326,7 +326,7 @@ LL |     foo::<u64>(42_i16);
 help: change the type of the numeric literal from `i16` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:71:16
@@ -337,7 +337,7 @@ LL |     foo::<u64>(42_i8);
 help: change the type of the numeric literal from `i8` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:73:16
@@ -348,7 +348,7 @@ LL |     foo::<u64>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u64`
    |
 LL |     foo::<u64>(42u64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:75:16
@@ -359,7 +359,7 @@ LL |     foo::<u64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u64`
    |
 LL |     foo::<u64>(42u64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:78:16
@@ -370,7 +370,7 @@ LL |     foo::<i64>(42_usize);
 help: change the type of the numeric literal from `usize` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:80:16
@@ -381,7 +381,7 @@ LL |     foo::<i64>(42_u64);
 help: change the type of the numeric literal from `u64` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:82:16
@@ -392,7 +392,7 @@ LL |     foo::<i64>(42_u32);
 help: change the type of the numeric literal from `u32` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:84:16
@@ -403,7 +403,7 @@ LL |     foo::<i64>(42_u16);
 help: change the type of the numeric literal from `u16` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:86:16
@@ -414,7 +414,7 @@ LL |     foo::<i64>(42_u8);
 help: change the type of the numeric literal from `u8` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:88:16
@@ -425,7 +425,7 @@ LL |     foo::<i64>(42_isize);
 help: change the type of the numeric literal from `isize` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:91:16
@@ -436,7 +436,7 @@ LL |     foo::<i64>(42_i32);
 help: change the type of the numeric literal from `i32` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:93:16
@@ -447,7 +447,7 @@ LL |     foo::<i64>(42_i16);
 help: change the type of the numeric literal from `i16` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:95:16
@@ -458,7 +458,7 @@ LL |     foo::<i64>(42_i8);
 help: change the type of the numeric literal from `i8` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:97:16
@@ -469,7 +469,7 @@ LL |     foo::<i64>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i64`
    |
 LL |     foo::<i64>(42i64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:99:16
@@ -480,7 +480,7 @@ LL |     foo::<i64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i64`
    |
 LL |     foo::<i64>(42i64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:102:16
@@ -491,7 +491,7 @@ LL |     foo::<u32>(42_usize);
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:104:16
@@ -502,7 +502,7 @@ LL |     foo::<u32>(42_u64);
 help: change the type of the numeric literal from `u64` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:107:16
@@ -513,7 +513,7 @@ LL |     foo::<u32>(42_u16);
 help: change the type of the numeric literal from `u16` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:109:16
@@ -524,7 +524,7 @@ LL |     foo::<u32>(42_u8);
 help: change the type of the numeric literal from `u8` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:111:16
@@ -535,7 +535,7 @@ LL |     foo::<u32>(42_isize);
 help: change the type of the numeric literal from `isize` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:113:16
@@ -546,7 +546,7 @@ LL |     foo::<u32>(42_i64);
 help: change the type of the numeric literal from `i64` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:115:16
@@ -557,7 +557,7 @@ LL |     foo::<u32>(42_i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:117:16
@@ -568,7 +568,7 @@ LL |     foo::<u32>(42_i16);
 help: change the type of the numeric literal from `i16` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:119:16
@@ -579,7 +579,7 @@ LL |     foo::<u32>(42_i8);
 help: change the type of the numeric literal from `i8` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:121:16
@@ -590,7 +590,7 @@ LL |     foo::<u32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u32`
    |
 LL |     foo::<u32>(42u32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:123:16
@@ -601,7 +601,7 @@ LL |     foo::<u32>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u32`
    |
 LL |     foo::<u32>(42u32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:126:16
@@ -612,7 +612,7 @@ LL |     foo::<i32>(42_usize);
 help: change the type of the numeric literal from `usize` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:128:16
@@ -623,7 +623,7 @@ LL |     foo::<i32>(42_u64);
 help: change the type of the numeric literal from `u64` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:130:16
@@ -634,7 +634,7 @@ LL |     foo::<i32>(42_u32);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:132:16
@@ -645,7 +645,7 @@ LL |     foo::<i32>(42_u16);
 help: change the type of the numeric literal from `u16` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:134:16
@@ -656,7 +656,7 @@ LL |     foo::<i32>(42_u8);
 help: change the type of the numeric literal from `u8` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:136:16
@@ -667,7 +667,7 @@ LL |     foo::<i32>(42_isize);
 help: change the type of the numeric literal from `isize` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:138:16
@@ -678,7 +678,7 @@ LL |     foo::<i32>(42_i64);
 help: change the type of the numeric literal from `i64` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:141:16
@@ -689,7 +689,7 @@ LL |     foo::<i32>(42_i16);
 help: change the type of the numeric literal from `i16` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:143:16
@@ -700,7 +700,7 @@ LL |     foo::<i32>(42_i8);
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:145:16
@@ -711,7 +711,7 @@ LL |     foo::<i32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i32`
    |
 LL |     foo::<i32>(42i32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:147:16
@@ -722,7 +722,7 @@ LL |     foo::<i32>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i32`
    |
 LL |     foo::<i32>(42i32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:150:16
@@ -733,7 +733,7 @@ LL |     foo::<u16>(42_usize);
 help: change the type of the numeric literal from `usize` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:152:16
@@ -744,7 +744,7 @@ LL |     foo::<u16>(42_u64);
 help: change the type of the numeric literal from `u64` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:154:16
@@ -755,7 +755,7 @@ LL |     foo::<u16>(42_u32);
 help: change the type of the numeric literal from `u32` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:157:16
@@ -766,7 +766,7 @@ LL |     foo::<u16>(42_u8);
 help: change the type of the numeric literal from `u8` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:159:16
@@ -777,7 +777,7 @@ LL |     foo::<u16>(42_isize);
 help: change the type of the numeric literal from `isize` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:161:16
@@ -788,7 +788,7 @@ LL |     foo::<u16>(42_i64);
 help: change the type of the numeric literal from `i64` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:163:16
@@ -799,7 +799,7 @@ LL |     foo::<u16>(42_i32);
 help: change the type of the numeric literal from `i32` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:165:16
@@ -810,7 +810,7 @@ LL |     foo::<u16>(42_i16);
 help: change the type of the numeric literal from `i16` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:167:16
@@ -821,7 +821,7 @@ LL |     foo::<u16>(42_i8);
 help: change the type of the numeric literal from `i8` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:169:16
@@ -832,7 +832,7 @@ LL |     foo::<u16>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u16`
    |
 LL |     foo::<u16>(42u16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:171:16
@@ -843,7 +843,7 @@ LL |     foo::<u16>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u16`
    |
 LL |     foo::<u16>(42u16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:174:16
@@ -854,7 +854,7 @@ LL |     foo::<i16>(42_usize);
 help: change the type of the numeric literal from `usize` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:176:16
@@ -865,7 +865,7 @@ LL |     foo::<i16>(42_u64);
 help: change the type of the numeric literal from `u64` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:178:16
@@ -876,7 +876,7 @@ LL |     foo::<i16>(42_u32);
 help: change the type of the numeric literal from `u32` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:180:16
@@ -887,7 +887,7 @@ LL |     foo::<i16>(42_u16);
 help: change the type of the numeric literal from `u16` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:182:16
@@ -898,7 +898,7 @@ LL |     foo::<i16>(42_u8);
 help: change the type of the numeric literal from `u8` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:184:16
@@ -909,7 +909,7 @@ LL |     foo::<i16>(42_isize);
 help: change the type of the numeric literal from `isize` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:186:16
@@ -920,7 +920,7 @@ LL |     foo::<i16>(42_i64);
 help: change the type of the numeric literal from `i64` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:188:16
@@ -931,7 +931,7 @@ LL |     foo::<i16>(42_i32);
 help: change the type of the numeric literal from `i32` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:191:16
@@ -942,7 +942,7 @@ LL |     foo::<i16>(42_i8);
 help: change the type of the numeric literal from `i8` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:193:16
@@ -953,7 +953,7 @@ LL |     foo::<i16>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i16`
    |
 LL |     foo::<i16>(42i16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:195:16
@@ -964,7 +964,7 @@ LL |     foo::<i16>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i16`
    |
 LL |     foo::<i16>(42i16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:198:15
@@ -975,7 +975,7 @@ LL |     foo::<u8>(42_usize);
 help: change the type of the numeric literal from `usize` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:200:15
@@ -986,7 +986,7 @@ LL |     foo::<u8>(42_u64);
 help: change the type of the numeric literal from `u64` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:202:15
@@ -997,7 +997,7 @@ LL |     foo::<u8>(42_u32);
 help: change the type of the numeric literal from `u32` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:204:15
@@ -1008,7 +1008,7 @@ LL |     foo::<u8>(42_u16);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:207:15
@@ -1019,7 +1019,7 @@ LL |     foo::<u8>(42_isize);
 help: change the type of the numeric literal from `isize` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:209:15
@@ -1030,7 +1030,7 @@ LL |     foo::<u8>(42_i64);
 help: change the type of the numeric literal from `i64` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:211:15
@@ -1041,7 +1041,7 @@ LL |     foo::<u8>(42_i32);
 help: change the type of the numeric literal from `i32` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:213:15
@@ -1052,7 +1052,7 @@ LL |     foo::<u8>(42_i16);
 help: change the type of the numeric literal from `i16` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:215:15
@@ -1063,7 +1063,7 @@ LL |     foo::<u8>(42_i8);
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:217:15
@@ -1074,7 +1074,7 @@ LL |     foo::<u8>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u8`
    |
 LL |     foo::<u8>(42u8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:219:15
@@ -1085,7 +1085,7 @@ LL |     foo::<u8>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u8`
    |
 LL |     foo::<u8>(42u8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:222:15
@@ -1096,7 +1096,7 @@ LL |     foo::<i8>(42_usize);
 help: change the type of the numeric literal from `usize` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:224:15
@@ -1107,7 +1107,7 @@ LL |     foo::<i8>(42_u64);
 help: change the type of the numeric literal from `u64` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:226:15
@@ -1118,7 +1118,7 @@ LL |     foo::<i8>(42_u32);
 help: change the type of the numeric literal from `u32` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:228:15
@@ -1129,7 +1129,7 @@ LL |     foo::<i8>(42_u16);
 help: change the type of the numeric literal from `u16` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:230:15
@@ -1140,7 +1140,7 @@ LL |     foo::<i8>(42_u8);
 help: change the type of the numeric literal from `u8` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:232:15
@@ -1151,7 +1151,7 @@ LL |     foo::<i8>(42_isize);
 help: change the type of the numeric literal from `isize` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:234:15
@@ -1162,7 +1162,7 @@ LL |     foo::<i8>(42_i64);
 help: change the type of the numeric literal from `i64` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:236:15
@@ -1173,7 +1173,7 @@ LL |     foo::<i8>(42_i32);
 help: change the type of the numeric literal from `i32` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:238:15
@@ -1184,7 +1184,7 @@ LL |     foo::<i8>(42_i16);
 help: change the type of the numeric literal from `i16` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:241:15
@@ -1195,7 +1195,7 @@ LL |     foo::<i8>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i8`
    |
 LL |     foo::<i8>(42i8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:243:15
@@ -1206,7 +1206,7 @@ LL |     foo::<i8>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i8`
    |
 LL |     foo::<i8>(42i8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:246:16
@@ -1217,7 +1217,7 @@ LL |     foo::<f64>(42_usize);
 help: change the type of the numeric literal from `usize` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:248:16
@@ -1228,7 +1228,7 @@ LL |     foo::<f64>(42_u64);
 help: change the type of the numeric literal from `u64` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:250:16
@@ -1239,7 +1239,7 @@ LL |     foo::<f64>(42_u32);
 help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u32.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:252:16
@@ -1250,7 +1250,7 @@ LL |     foo::<f64>(42_u16);
 help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:254:16
@@ -1261,7 +1261,7 @@ LL |     foo::<f64>(42_u8);
 help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:256:16
@@ -1272,7 +1272,7 @@ LL |     foo::<f64>(42_isize);
 help: change the type of the numeric literal from `isize` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:258:16
@@ -1283,7 +1283,7 @@ LL |     foo::<f64>(42_i64);
 help: change the type of the numeric literal from `i64` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:260:16
@@ -1294,7 +1294,7 @@ LL |     foo::<f64>(42_i32);
 help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i32.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:262:16
@@ -1305,7 +1305,7 @@ LL |     foo::<f64>(42_i16);
 help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:264:16
@@ -1316,7 +1316,7 @@ LL |     foo::<f64>(42_i8);
 help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:267:16
@@ -1327,7 +1327,7 @@ LL |     foo::<f64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `f64`
    |
 LL |     foo::<f64>(42.0_f64);
-   |                ~~~~~~~~
+   |                     ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:270:16
@@ -1338,7 +1338,7 @@ LL |     foo::<f32>(42_usize);
 help: change the type of the numeric literal from `usize` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:272:16
@@ -1349,7 +1349,7 @@ LL |     foo::<f32>(42_u64);
 help: change the type of the numeric literal from `u64` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:274:16
@@ -1360,7 +1360,7 @@ LL |     foo::<f32>(42_u32);
 help: change the type of the numeric literal from `u32` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:276:16
@@ -1371,7 +1371,7 @@ LL |     foo::<f32>(42_u16);
 help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_u16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:278:16
@@ -1382,7 +1382,7 @@ LL |     foo::<f32>(42_u8);
 help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_u8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:280:16
@@ -1393,7 +1393,7 @@ LL |     foo::<f32>(42_isize);
 help: change the type of the numeric literal from `isize` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:282:16
@@ -1404,7 +1404,7 @@ LL |     foo::<f32>(42_i64);
 help: change the type of the numeric literal from `i64` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:284:16
@@ -1415,7 +1415,7 @@ LL |     foo::<f32>(42_i32);
 help: change the type of the numeric literal from `i32` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:286:16
@@ -1426,7 +1426,7 @@ LL |     foo::<f32>(42_i16);
 help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_i16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:288:16
@@ -1437,7 +1437,7 @@ LL |     foo::<f32>(42_i8);
 help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_i8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:290:16
@@ -1448,25 +1448,29 @@ LL |     foo::<f32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `f32`
    |
 LL |     foo::<f32>(42.0_f32);
-   |                ~~~~~~~~
+   |                     ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:294:16
    |
 LL |     foo::<u32>(42_u8 as u16);
-   |                ^^^^^^^^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `(42_u8 as u16).into()`
+   |                ^^^^^^^^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>((42_u8 as u16).into());
+   |                +            ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:296:16
    |
 LL |     foo::<i32>(-42_i8);
-   |                ^^^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `(-42_i8).into()`
+   |                ^^^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>((-42_i8).into());
+   |                +      ++++++++
 
 error: aborting due to 134 previous errors
 
index bf1641167cf1184de4ee5fc1001746a1ae5e222f..f1dd508a4674163c32e8ec6783793c62fd891db5 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
   --> $DIR/object-does-not-impl-trait.rs:6:44
    |
 LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-   |                                            ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   |
+   |                                   required by a bound introduced by this call
    |
 note: required by a bound in `take_foo`
   --> $DIR/object-does-not-impl-trait.rs:5:15
index 79ded5fc875a2d41c97b53c761bf26d9efb5b10b..ee1a4612572281fd11c2f57717a534350167c5a9 100644 (file)
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
    |
 LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
    |             ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/object-lifetime-default-elision.rs:71:5
    |
 LL |     ss
@@ -48,7 +48,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
    |
 LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait {
    |             ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/object-lifetime-default-elision.rs:71:5
    |
 LL |     ss
index 35ec586892c05b13e2934aba8465dfee635f9a2e..9dd144fee24a68550116fb5ebf82292c0cc3607b 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` 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-associated-consts.rs:9:11
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
 
 error: aborting due to previous error
 
index d51734ed2316bbf1627a665e82fd338801617f28..9ba3b251e66034d207640e2cadd95609a8c6f07c 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` 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-associated-consts.rs:9:11
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
index 8d6094c5144290c68ca2bc0def7f61368b4fa25f..345950f1ae670cb473598f10e32a51c4d7d09d94 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-generics.rs:10:8
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-generics.rs:24:39
@@ -19,7 +19,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
    |                                       ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-generics.rs:10:8
    |
@@ -27,6 +26,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
 
 error: aborting due to 2 previous errors
 
index 3d2b2bb228cb529395c185dc71bbaf897a77d2ea..86355627c796f9040d82f9c48686c4518f2771a8 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-generics.rs:10:8
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
@@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t as &dyn Bar
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-generics.rs:10:8
    |
@@ -29,6 +28,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
index 336929702e6cd3d032a9f24efa3cbd7356df1d41..f91c9b9856055778e20bbf4ae4d39fa5f1fe1caf 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-mentions-Self.rs:11:22
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Baz` cannot be made into an object
   --> $DIR/object-safety-mentions-Self.rs:28:30
@@ -19,7 +19,6 @@ error[E0038]: the trait `Baz` cannot be made into an object
 LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    |                              ^^^^^^^^ `Baz` cannot be made into an object
    |
-   = help: consider moving `baz` 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-mentions-Self.rs:15:22
    |
@@ -27,6 +26,7 @@ LL | trait Baz {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
 
 error: aborting due to 2 previous errors
 
index 6e7896e309cc691ec9b20182800625b587f2e29a..f48628c9d1111fd24e5d847bb4b6855f6075cfa7 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` 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-mentions-Self.rs:11:22
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
@@ -21,7 +21,6 @@ error[E0038]: the trait `Baz` cannot be made into an object
 LL |     t
    |     ^ `Baz` cannot be made into an object
    |
-   = help: consider moving `baz` 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-mentions-Self.rs:15:22
    |
@@ -29,6 +28,7 @@ LL | trait Baz {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T`
    = note: required by cast to type `&dyn Baz`
 
index abd156dd5ac4a74198a82f6c5c94c2773c836066..67759d02a161e83db474b5275ba1ac167bee02b8 100644 (file)
@@ -4,7 +4,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied
 LL |       let x = || {
    |  _____________-
 LL | |         f(Foo{});
-   | |           ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |         - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |         |
+   | |         required by a bound introduced by this call
 LL | |         let y = || {
 LL | |             f(Foo{});
 LL | |         };
@@ -23,7 +25,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied
 LL |           let y = || {
    |  _________________-
 LL | |             f(Foo{});
-   | |               ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             |
+   | |             required by a bound introduced by this call
 LL | |         };
    | |_________- in this scope
    |
@@ -42,7 +46,9 @@ LL | |         f(Foo{});
 LL | |         let y = || {
 ...  |
 LL | |             f(Foo{});
-   | |               ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             |
+   | |             required by a bound introduced by this call
 ...  |
 LL | |     f(Foo{});
 LL | | }
@@ -63,7 +69,9 @@ LL | |         f(Foo{});
 LL | |         let y = || {
 ...  |
 LL | |     f(Foo{});
-   | |       ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |     - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |     |
+   | |     required by a bound introduced by this call
 LL | | }
    | |_- in this scope
    |
index 804b6282202be85cd9082d4bab3c18233cbcca47..a3658f224260633b69b14b9503596b588fb49a56 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:18
    |
 LL |     Index::index(&[] as &[i32], 2u32);
-   |                  ^^^^^^^^^^^^^ trait message
+   |     ------------ ^^^^^^^^^^^^^ trait message
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
 note: required by `Index::index`
@@ -15,7 +17,9 @@ error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:18
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
-   |                  ^^^^^^^^^^^^^ on impl for Foo
+   |     ------------ ^^^^^^^^^^^^^ on impl for Foo
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
 note: required by `Index::index`
@@ -28,7 +32,9 @@ error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:18
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
-   |                  ^^^^^^^^^^^^^ on impl for Bar
+   |     ------------ ^^^^^^^^^^^^^ on impl for Bar
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
 note: required by `Index::index`
index bfd438e5cc215212efa3983cd252901ce12a56fc..18eca06ba698111d36a1b8c1b6424b23a7127eef 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:25
    |
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
-   |                         ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
 note: required by `Index::index`
diff --git a/src/test/ui/out-of-order-shadowing.rs b/src/test/ui/out-of-order-shadowing.rs
deleted file mode 100644 (file)
index a0d1a97..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// aux-build:define-macro.rs
-
-macro_rules! bar { () => {} }
-define_macro!(bar);
-bar!(); //~ ERROR `bar` is ambiguous
-
-macro_rules! m { () => { #[macro_use] extern crate define_macro; } }
-m!();
-
-fn main() {}
diff --git a/src/test/ui/out-of-order-shadowing.stderr b/src/test/ui/out-of-order-shadowing.stderr
deleted file mode 100644 (file)
index 1db31e0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0659]: `bar` is ambiguous (macro-expanded name vs less macro-expanded name from outer scope during import/macro resolution)
-  --> $DIR/out-of-order-shadowing.rs:5:1
-   |
-LL | bar!();
-   | ^^^ ambiguous name
-   |
-note: `bar` could refer to the macro defined here
-  --> $DIR/out-of-order-shadowing.rs:4:1
-   |
-LL | define_macro!(bar);
-   | ^^^^^^^^^^^^^^^^^^^
-note: `bar` could also refer to the macro defined here
-  --> $DIR/out-of-order-shadowing.rs:3:1
-   |
-LL | macro_rules! bar { () => {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `define_macro` (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 E0659`.
index 1ae16d2a7fc66eed75fc62d3836343cbca404223..f48bae55f5f1e820063df9c290b47ef4ce53b5c6 100644 (file)
@@ -1,5 +1,7 @@
 // run-pass
 
+#![allow(dead_code)]
+
 use std::rc::Rc;
 use std::ops::Deref;
 
index 5f5e25991e0cc732dffa898cf5ede8fe6785476c..101959d6da0e0ae36daffadaecd581aac2af43db 100644 (file)
@@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
     }) > 0 //~ ERROR expected expression
 }
 
+fn qux() -> u32 {
+    ({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
index 5428e1c32fed3edbe0a9bef2cf7c890b3ce6246e..45c4f977502d24fc0414b854c5fb843792cf331c 100644 (file)
@@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
     } > 0 //~ ERROR expected expression
 }
 
+fn qux() -> u32 {
+    {2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
index d99e9be0000c312ef65101aef774f070e78f8cd2..cae775099e0a03ced8306d34efbe54a3df257290 100644 (file)
@@ -99,7 +99,29 @@ help: parentheses are required to parse this as an expression
 LL |     ({ 3 }) * 3
    |     +     +
 
-error: aborting due to 9 previous errors
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:36:6
+   |
+LL |     {2} - 2
+   |      ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     {return 2;} - 2
+   |      ++++++  +
+
+error[E0600]: cannot apply unary operator `-` to type `u32`
+  --> $DIR/expr-as-stmt.rs:36:9
+   |
+LL |     {2} - 2
+   |         ^^^ cannot apply unary operator `-`
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     ({2}) - 2
+   |     +   +
+
+error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0308, E0614.
+Some errors have detailed explanations: E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0308`.
index d1a249389fe5c8bf4adec2b0652de501f3574ddf..86622778203905c61018558c15871cc3d0fad4ed 100644 (file)
@@ -38,15 +38,15 @@ LL | fn fizz(i32) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn fizz(self: i32) {}
-   |         ~~~~~~~~~
+   |         +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn fizz(i32: TypeName) {}
-   |         ~~~~~~~~~~~~~
+   |            ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn fizz(_: i32) {}
-   |         ~~~~~~
+   |         ++
 
 error: expected one of `:`, `@`, or `|`, found `S`
   --> $DIR/inverted-parameters.rs:27:23
index 83bbf884a4ff8da4a617e80022ad1bc4df62af65..a5b7e83a016223848f319673aea1dacefdf8ce17 100644 (file)
@@ -1,10 +1,10 @@
 macro_rules! foo {
     ($rest: tt) => {
-        bar(baz: $rest)
+        bar(baz: $rest) //~ ERROR invalid `struct` delimiters or `fn` call arguments
     }
 }
 
 fn main() {
-    foo!(true); //~ ERROR expected type, found keyword
+    foo!(true);
     //~^ ERROR expected identifier, found keyword
 }
index 372387131e54b5c0c05ace1a17b67150846d526b..862026408ef7f8d9db8a9631a37f9b2f98c70f4e 100644 (file)
@@ -9,17 +9,25 @@ help: you can escape reserved keywords to use them as identifiers
 LL |     foo!(r#true);
    |          ~~~~~~
 
-error: expected type, found keyword `true`
-  --> $DIR/issue-44406.rs:8:10
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-44406.rs:3:9
    |
 LL |         bar(baz: $rest)
-   |                - help: try using a semicolon: `;`
+   |         ^^^^^^^^^^^^^^^
 ...
 LL |     foo!(true);
-   |          ^^^^ expected type
+   |     ----------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: if `bar` is a struct, use braces as delimiters
+   |
+LL |         bar {  }
+   |             ~
+help: if `bar` is a function, use the arguments directly
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+LL -         bar(baz: $rest)
+LL +         bar(true);
+   | 
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/issue-88583-union-as-ident.rs b/src/test/ui/parser/issue-88583-union-as-ident.rs
new file mode 100644 (file)
index 0000000..b3d66d4
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+#![allow(non_camel_case_types)]
+
+struct union;
+
+impl union {
+    pub fn new() -> Self {
+        union { }
+    }
+}
+
+fn main() {
+    let _u = union::new();
+}
diff --git a/src/test/ui/parser/issue-88818.rs b/src/test/ui/parser/issue-88818.rs
new file mode 100644 (file)
index 0000000..b9233ca
--- /dev/null
@@ -0,0 +1,10 @@
+// Regression test for #88818 (improve error message for missing trait
+// in `impl for X`).
+
+struct S { }
+impl for S { }
+//~^ ERROR: missing trait in a trait impl
+//~| HELP: add a trait here
+//~| HELP: for an inherent impl, drop this `for`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-88818.stderr b/src/test/ui/parser/issue-88818.stderr
new file mode 100644 (file)
index 0000000..d30990a
--- /dev/null
@@ -0,0 +1,18 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-88818.rs:5:5
+   |
+LL | impl for S { }
+   |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for S { }
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for S { }
+LL + impl S { }
+   | 
+
+error: aborting due to previous error
+
index bf73595e5b0817c515722447423ab9ed14131ad4..a1d721e746ad02fc00998966dd158e9b0e2b0345 100644 (file)
@@ -13,16 +13,16 @@ LL | fn test(&'a str) {
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
 help: if this is a `self` type, give it a parameter name
    |
-LL | fn test(self: &str) {
-   |         ~~~~~~~~~~
+LL | fn test(self: &'a str) {
+   |         +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn test(str: &TypeName) {
    |         ~~~~~~~~~~~~~~
 help: if this is a type, explicitly ignore the parameter name
    |
-LL | fn test(_: &str) {
-   |         ~~~~~~~
+LL | fn test(_: &'a str) {
+   |         ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/macro-braces-dot-question.rs b/src/test/ui/parser/macro-braces-dot-question.rs
new file mode 100644 (file)
index 0000000..016b434
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+
+use std::io::Write;
+
+fn main() -> Result<(), std::io::Error> {
+    vec! { 1, 2, 3 }.len();
+    write! { vec![], "" }?;
+    println!{""}
+    [0]; // separate statement, not indexing into the result of println.
+    Ok(())
+}
index 329fa8776f5aff7e9f6e02e813bfeada24a470aa..ce2eab051addd3feca87b91313af10c6de6e514f 100644 (file)
@@ -8,15 +8,15 @@ LL | fn foo(x) {
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn foo(self: x) {
-   |        ~~~~~~~
+   |        +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn foo(x: TypeName) {
-   |        ~~~~~~~~~~~
+   |         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(_: x) {
-   |        ~~~~
+   |        ++
 
 error: aborting due to previous error
 
index 762733cc97ba3496572db697455c7a4236b4c790..c78f96e1addcb21f5b6ffe213f706cacc91b65a5 100644 (file)
@@ -8,11 +8,11 @@ LL | fn a(B<) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn a(self: B<) {}
-   |      ~~~~~~~
+   |      +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn a(_: B<) {}
-   |      ~~~~
+   |      ++
 
 error: aborting due to previous error
 
index 779e1646344787b680be00576c3e9d588791201d..8080dbc332ae7146d13648157bc3e64fde3f2f77 100644 (file)
@@ -9,7 +9,7 @@ fn main() {
 
     for ( elem in vec ) {
         //~^ ERROR expected one of `)`, `,`, `@`, or `|`, found keyword `in`
-        //~| ERROR unexpected closing `)`
+        //~| ERROR unexpected parenthesis surrounding `for` loop head
         const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
     }
 }
index e97cf544ac2683d3df171e902c96ce71f753dfad..21991348327b36e99d5f4c67b9aa5e2057b91a91 100644 (file)
@@ -4,14 +4,17 @@ error: expected one of `)`, `,`, `@`, or `|`, found keyword `in`
 LL |     for ( elem in vec ) {
    |                ^^ expected one of `)`, `,`, `@`, or `|`
 
-error: unexpected closing `)`
-  --> $DIR/recover-for-loop-parens-around-head.rs:10:23
+error: unexpected parenthesis surrounding `for` loop head
+  --> $DIR/recover-for-loop-parens-around-head.rs:10:9
    |
 LL |     for ( elem in vec ) {
-   |         --------------^
-   |         |
-   |         opening `(`
-   |         help: remove parenthesis in `for` loop: `elem in vec`
+   |         ^             ^
+   |
+help: remove parenthesis in `for` loop
+   |
+LL -     for ( elem in vec ) {
+LL +     for  elem in vec  {
+   | 
 
 error[E0308]: mismatched types
   --> $DIR/recover-for-loop-parens-around-head.rs:13:38
index 1bcef450bb9be4706477d6367ec7cb91c7da1058..e8887147cbc863a9debfa7ac8b91547874034b16 100644 (file)
@@ -5,7 +5,7 @@ enum Enum {
 
 fn main() {
     let x = Enum::Foo(a: 3, b: 4);
-    //~^ ERROR expected type, found `3`
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
     match x {
         Enum::Foo(a, b) => {}
         //~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
index 61ea3695eee0b1adc4960b7705553393442ddab8..8cb71069bdaaca5f3c08eaf17b521e68bc255d7f 100644 (file)
@@ -1,13 +1,18 @@
-error: expected type, found `3`
-  --> $DIR/recover-from-bad-variant.rs:7:26
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/recover-from-bad-variant.rs:7:13
    |
 LL |     let x = Enum::Foo(a: 3, b: 4);
-   |                        - ^ expected type
-   |                        |
-   |                        tried to parse a type due to this type ascription
+   |             ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Enum::Foo` is a struct, use braces as delimiters
+   |
+LL |     let x = Enum::Foo { a: 3, b: 4 };
+   |                       ~            ~
+help: if `Enum::Foo` is a function, use the arguments directly
+   |
+LL -     let x = Enum::Foo(a: 3, b: 4);
+LL +     let x = Enum::Foo(3, 4);
+   | 
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
   --> $DIR/recover-from-bad-variant.rs:10:9
diff --git a/src/test/ui/parser/unicode-character-literal.fixed b/src/test/ui/parser/unicode-character-literal.fixed
new file mode 100644 (file)
index 0000000..26ef5ff
--- /dev/null
@@ -0,0 +1,21 @@
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+    let _spade = "♠️";
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+    //~| HELP: if you meant to write a `str` literal, use double quotes
+
+    let _s = "ṩ̂̊";
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+    //~| HELP: if you meant to write a `str` literal, use double quotes
+
+    let _a = 'Å';
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+    //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
diff --git a/src/test/ui/parser/unicode-character-literal.rs b/src/test/ui/parser/unicode-character-literal.rs
new file mode 100644 (file)
index 0000000..d331522
--- /dev/null
@@ -0,0 +1,21 @@
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+    let _spade = '♠️';
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+    //~| HELP: if you meant to write a `str` literal, use double quotes
+
+    let _s = 'ṩ̂̊';
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+    //~| HELP: if you meant to write a `str` literal, use double quotes
+
+    let _a = 'Å';
+    //~^ ERROR: character literal may only contain one codepoint
+    //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+    //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
diff --git a/src/test/ui/parser/unicode-character-literal.stderr b/src/test/ui/parser/unicode-character-literal.stderr
new file mode 100644 (file)
index 0000000..5cd3bd0
--- /dev/null
@@ -0,0 +1,48 @@
+error: character literal may only contain one codepoint
+  --> $DIR/unicode-character-literal.rs:7:18
+   |
+LL |     let _spade = '♠️';
+   |                  ^^^
+   |
+note: this `♠` is followed by the combining mark `\u{fe0f}`
+  --> $DIR/unicode-character-literal.rs:7:19
+   |
+LL |     let _spade = '♠️';
+   |                   ^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _spade = "♠️";
+   |                  ~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/unicode-character-literal.rs:12:14
+   |
+LL |     let _s = 'ṩ̂̊';
+   |              ^^^
+   |
+note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+  --> $DIR/unicode-character-literal.rs:12:15
+   |
+LL |     let _s = 'ṩ̂̊';
+   |               ^
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _s = "ṩ̂̊";
+   |              ~~~
+
+error: character literal may only contain one codepoint
+  --> $DIR/unicode-character-literal.rs:17:14
+   |
+LL |     let _a = 'Å';
+   |              ^-^
+   |               |
+   |               help: consider using the normalized form `\u{c5}` of this character: `Å`
+   |
+note: this `A` is followed by the combining mark `\u{30a}`
+  --> $DIR/unicode-character-literal.rs:17:15
+   |
+LL |     let _a = 'Å';
+   |               ^
+
+error: aborting due to 3 previous errors
+
index dcf235a9e277455079318ec30f933f6ae57a03da..8adf02b150b874cf2577068fae6e0c9bd5502327 100644 (file)
@@ -2,13 +2,18 @@ warning: unnecessary parentheses around `return` value
   --> $DIR/path-lookahead.rs:10:12
    |
 LL |     return (<T as ToString>::to_string(&arg));
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |            ^                                ^
    |
 note: the lint level is defined here
   --> $DIR/path-lookahead.rs:5:9
    |
 LL | #![warn(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     return (<T as ToString>::to_string(&arg));
+LL +     return <T as ToString>::to_string(&arg);
+   | 
 
 warning: 1 warning emitted
 
index e7b5528daee920d48cd64e97bebb67751be27d9b..1cc653c51cfa1244b46ebeca5f7a71b678c648a6 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-auto-trait.rs:21:12
    |
 LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
+   |     ------ ^ `T` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Zen` for `&T`
   --> $DIR/phantom-auto-trait.rs:10:24
@@ -29,7 +31,9 @@ error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-auto-trait.rs:26:12
    |
 LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
+   |     ------ ^ `T` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Zen` for `&T`
   --> $DIR/phantom-auto-trait.rs:10:24
diff --git a/src/test/ui/polymorphization/issue-74614.rs b/src/test/ui/polymorphization/issue-74614.rs
new file mode 100644 (file)
index 0000000..8b0c00b
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags:-Zpolymorphize=on
+// build-pass
+
+fn test<T>() {
+    std::mem::size_of::<T>();
+}
+
+pub fn foo<T>(_: T) -> &'static fn() {
+    &(test::<T> as fn())
+}
+
+fn outer<T>() {
+    foo(|| ());
+}
+
+fn main() {
+    outer::<u8>();
+}
index c42d9e6bbf0fcbcacadab027882df9a97d0e8cf7..49895f3db4dff417b3967215b97a8ef308c8c33c 100644 (file)
@@ -7,7 +7,7 @@ LL |     let_in(3u32, |i| { assert!(i == 3i32); });
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     let_in(3u32, |i| { assert!(i == 3u32); });
-   |                                     ~~~~
+   |                                      ~~~
 
 error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:8:37
@@ -18,7 +18,7 @@ LL |     let_in(3i32, |i| { assert!(i == 3u32); });
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     let_in(3i32, |i| { assert!(i == 3i32); });
-   |                                     ~~~~
+   |                                      ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/privacy/issue-79593.rs b/src/test/ui/privacy/issue-79593.rs
new file mode 100644 (file)
index 0000000..b94278b
--- /dev/null
@@ -0,0 +1,29 @@
+mod foo {
+    pub struct Pub { private: () }
+
+    pub enum Enum {
+        Variant { x: (), y: () },
+        Other
+    }
+
+    fn correct() {
+        Pub {};
+        //~^ ERROR missing field `private` in initializer of `Pub`
+        Enum::Variant { x: () };
+        //~^ ERROR missing field `y` in initializer of `Enum`
+    }
+}
+
+fn correct() {
+    foo::Pub {};
+    //~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields
+}
+
+fn wrong() {
+    foo::Enum::Variant { x: () };
+    //~^ ERROR missing field `y` in initializer of `Enum`
+    foo::Enum::Variant { };
+    //~^ ERROR missing fields `x` and `y` in initializer of `Enum`
+}
+
+fn main() {}
diff --git a/src/test/ui/privacy/issue-79593.stderr b/src/test/ui/privacy/issue-79593.stderr
new file mode 100644 (file)
index 0000000..b8c7d4f
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0063]: missing field `private` in initializer of `Pub`
+  --> $DIR/issue-79593.rs:10:9
+   |
+LL |         Pub {};
+   |         ^^^ missing `private`
+
+error[E0063]: missing field `y` in initializer of `Enum`
+  --> $DIR/issue-79593.rs:12:9
+   |
+LL |         Enum::Variant { x: () };
+   |         ^^^^^^^^^^^^^ missing `y`
+
+error: cannot construct `Pub` with struct literal syntax due to inaccessible fields
+  --> $DIR/issue-79593.rs:18:5
+   |
+LL |     foo::Pub {};
+   |     ^^^^^^^^
+
+error[E0063]: missing field `y` in initializer of `Enum`
+  --> $DIR/issue-79593.rs:23:5
+   |
+LL |     foo::Enum::Variant { x: () };
+   |     ^^^^^^^^^^^^^^^^^^ missing `y`
+
+error[E0063]: missing fields `x` and `y` in initializer of `Enum`
+  --> $DIR/issue-79593.rs:25:5
+   |
+LL |     foo::Enum::Variant { };
+   |     ^^^^^^^^^^^^^^^^^^ missing `x` and `y`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
index 713560772ee4c0dcea6069664ccd607f82e69708..e9a44ccb12e742adacd89e5c3f65595e11093c4b 100644 (file)
@@ -18,7 +18,7 @@ LL |         Some(x) => { return x },
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         Some(x) => { return x.try_into().unwrap() },
-   |                             ~~~~~~~~~~~~~~~~~~~~~
+   |                              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:33:22
index 1c8840f540e76712a11075f39fc710269926f2fd..852ca0f21b166190260c4fb9096f4ec475c28ee0 100644 (file)
@@ -69,7 +69,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |         ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/region-object-lifetime-in-coercion.rs:23:5
    |
 LL |     Box::new(v)
index 0cce89215d364a254eeb7aeea236b5bdeac6e414..bf29c76a0f0a8bcee9ea263faeb1c70a23224ec0 100644 (file)
@@ -19,7 +19,7 @@ note: but, the lifetime must be valid for the lifetime `'c` as defined on the fu
    |
 LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
    |                          ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
    |
 LL |     box v as Box<dyn SomeTrait + 'a>
index b24db1df18b0a9451470eac54ca3790da439be36..44bd88e01a267a0654a765fb4c4981a64dc78b28 100644 (file)
@@ -21,7 +21,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
    |
 LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> {
    |                   ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/regions-creating-enums4.rs:7:5
    |
 LL |     Ast::Add(x, y)
index bba968cfde43c1906db1cbb9b8808eb2c85e4854..b5b54bc3c8b735ebc97ab00f1a686961df752ea1 100644 (file)
@@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th
    |
 LL |     with(|o| o)
    |          ^^^^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/regions-ret-borrowed-1.rs:10:14
    |
 LL |     with(|o| o)
index 4b93ca0ae67346b6f8f7d5f1008a19c58eefbd60..debae47d16d0be13c52e83133dc592a4ad8d4edf 100644 (file)
@@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on th
    |
 LL |     with(|o| o)
    |          ^^^^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/regions-ret-borrowed.rs:13:14
    |
 LL |     with(|o| o)
index 7478b53bd3ccc02c7097f35f8aef4bad0918e205..f16dfdd6e8c77e17cb05b3c16839ffb9971d91ed 100644 (file)
@@ -36,7 +36,7 @@ note: but, the lifetime must be valid for the lifetime `'b` as defined on the fu
    |
 LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy {
    |            ^^
-note: ...so that the expression is assignable
+note: ...so that the types are compatible
   --> $DIR/regions-trait-object-subtyping.rs:15:5
    |
 LL |     x
index c85f057203146ffdc52157e9f903a196c862a5f2..59bcd954a1fde235c20e3c4d83b06e7dd7feca44 100644 (file)
@@ -55,7 +55,7 @@ LL |     let f = [0; 4u8];
 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
diff --git a/src/test/ui/repr/repr-transparent-issue-87496.rs b/src/test/ui/repr/repr-transparent-issue-87496.rs
new file mode 100644 (file)
index 0000000..a4dd45c
--- /dev/null
@@ -0,0 +1,12 @@
+// Regression test for the ICE described in #87496.
+
+// check-pass
+
+#[repr(transparent)]
+struct TransparentCustomZst(());
+extern "C" {
+    fn good17(p: TransparentCustomZst);
+    //~^ WARNING: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-transparent-issue-87496.stderr b/src/test/ui/repr/repr-transparent-issue-87496.stderr
new file mode 100644 (file)
index 0000000..c488755
--- /dev/null
@@ -0,0 +1,16 @@
+warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+  --> $DIR/repr-transparent-issue-87496.rs:8:18
+   |
+LL |     fn good17(p: TransparentCustomZst);
+   |                  ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: `#[warn(improper_ctypes)]` on by default
+   = note: this struct contains only zero-sized fields
+note: the type is defined here
+  --> $DIR/repr-transparent-issue-87496.rs:6:1
+   |
+LL | struct TransparentCustomZst(());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/resolve/issue-42944.rs b/src/test/ui/resolve/issue-42944.rs
new file mode 100644 (file)
index 0000000..a440485
--- /dev/null
@@ -0,0 +1,21 @@
+mod foo {
+    pub struct Bx(());
+}
+
+mod bar {
+    use foo::Bx;
+
+    fn foo() {
+        Bx(());
+        //~^ ERROR cannot initialize a tuple struct which contains private fields [E0423]
+    }
+}
+
+mod baz {
+    fn foo() {
+        Bx(());
+        //~^ ERROR cannot find function, tuple struct or tuple variant `Bx` in this scope [E0425]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-42944.stderr b/src/test/ui/resolve/issue-42944.stderr
new file mode 100644 (file)
index 0000000..0084925
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0423]: cannot initialize a tuple struct which contains private fields
+  --> $DIR/issue-42944.rs:9:9
+   |
+LL |         Bx(());
+   |         ^^
+   |
+note: constructor is not visible here due to private fields
+  --> $DIR/issue-42944.rs:2:19
+   |
+LL |     pub struct Bx(());
+   |                   ^^ private field
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
+  --> $DIR/issue-42944.rs:16:9
+   |
+LL |         Bx(());
+   |         ^^ not found in this scope
+   |
+help: consider importing this tuple struct
+   |
+LL |     use foo::Bx;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0425.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/resolve/use-self-in-inner-fn.rs b/src/test/ui/resolve/use-self-in-inner-fn.rs
new file mode 100644 (file)
index 0000000..eccb315
--- /dev/null
@@ -0,0 +1,14 @@
+struct A;
+
+impl A {
+//~^ NOTE `Self` type implicitly declared here, by this `impl`
+    fn banana(&mut self) {
+        fn peach(this: &Self) {
+        //~^ ERROR can't use generic parameters from outer function
+        //~| NOTE use of generic parameter from outer function
+        //~| NOTE use a type here instead
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/use-self-in-inner-fn.stderr b/src/test/ui/resolve/use-self-in-inner-fn.stderr
new file mode 100644 (file)
index 0000000..9660934
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0401]: can't use generic parameters from outer function
+  --> $DIR/use-self-in-inner-fn.rs:6:25
+   |
+LL | impl A {
+   | ---- `Self` type implicitly declared here, by this `impl`
+...
+LL |         fn peach(this: &Self) {
+   |                         ^^^^
+   |                         |
+   |                         use of generic parameter from outer function
+   |                         use a type here instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
index 8516bafef9bd9e9f45f03e5cb34da55bc92fd71e..0098f087d10f8dcf469d7d45683beb8683c871dd 100644 (file)
@@ -4,8 +4,29 @@
 pub enum NonExhaustiveEnum {
     Unit,
     Tuple(u32),
-    Struct { field: u32 }
+    Struct { field: u32 },
+}
+
+#[non_exhaustive]
+pub enum NestedNonExhaustive {
+    A(NonExhaustiveEnum),
+    B,
+    C,
 }
 
 #[non_exhaustive]
 pub enum EmptyNonExhaustiveEnum {}
+
+pub enum VariantNonExhaustive {
+    #[non_exhaustive]
+    Bar {
+        x: u32,
+        y: u64,
+    },
+    Baz(u32, u16),
+}
+
+#[non_exhaustive]
+pub enum NonExhaustiveSingleVariant {
+    A(bool),
+}
index 6bfe7bf923d0901e2cf5ddb92d31d86fc89d4604..5b2181d2d833b120688d2390e3cc3452b634b94b 100644 (file)
@@ -1,3 +1,4 @@
+#[derive(Default)]
 #[non_exhaustive]
 pub struct NormalStruct {
     pub first_field: u16,
@@ -15,7 +16,7 @@ pub struct NormalStruct {
 pub struct FunctionalRecord {
     pub first_field: u16,
     pub second_field: u16,
-    pub third_field: bool
+    pub third_field: bool,
 }
 
 impl Default for FunctionalRecord {
@@ -23,3 +24,10 @@ fn default() -> FunctionalRecord {
         FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
     }
 }
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NestedStruct {
+    pub foo: u16,
+    pub bar: NormalStruct,
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs
new file mode 100644 (file)
index 0000000..115fd30
--- /dev/null
@@ -0,0 +1,160 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+// aux-build:enums.rs
+extern crate enums;
+
+// aux-build:structs.rs
+extern crate structs;
+
+use enums::{
+    EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
+    VariantNonExhaustive,
+};
+use structs::{FunctionalRecord, NestedStruct, NormalStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+    a: u8,
+    b: usize,
+    c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+    A,
+    B,
+    C,
+}
+
+fn main() {
+    let enumeration = Bar::A;
+
+    // Ok: this is a crate local non_exhaustive enum
+    match enumeration {
+        Bar::A => {}
+        Bar::B => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+
+    let non_enum = NonExhaustiveEnum::Unit;
+
+    // Ok: without the attribute
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        _ => {}
+    }
+
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    match non_enum {
+        NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    let x = 5;
+    match non_enum {
+        NonExhaustiveEnum::Unit if x > 10 => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    // Ok: all covered and not `unreachable-patterns`
+    #[deny(unreachable_patterns)]
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NestedNonExhaustive::B {
+        NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+        NestedNonExhaustive::A(_) => {}
+        NestedNonExhaustive::B => {}
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+    //~^^^^^ some variants are not matched explicitly
+
+    // The io::ErrorKind has many `unstable` fields how do they interact with this
+    // lint
+    #[deny(non_exhaustive_omitted_patterns)]
+    match std::io::ErrorKind::Other {
+        std::io::ErrorKind::NotFound => {}
+        std::io::ErrorKind::PermissionDenied => {}
+        std::io::ErrorKind::ConnectionRefused => {}
+        std::io::ErrorKind::ConnectionReset => {}
+        std::io::ErrorKind::ConnectionAborted => {}
+        std::io::ErrorKind::NotConnected => {}
+        std::io::ErrorKind::AddrInUse => {}
+        std::io::ErrorKind::AddrNotAvailable => {}
+        std::io::ErrorKind::BrokenPipe => {}
+        std::io::ErrorKind::AlreadyExists => {}
+        std::io::ErrorKind::WouldBlock => {}
+        std::io::ErrorKind::InvalidInput => {}
+        std::io::ErrorKind::InvalidData => {}
+        std::io::ErrorKind::TimedOut => {}
+        std::io::ErrorKind::WriteZero => {}
+        std::io::ErrorKind::Interrupted => {}
+        std::io::ErrorKind::Other => {}
+        std::io::ErrorKind::UnexpectedEof => {}
+        std::io::ErrorKind::Unsupported => {}
+        std::io::ErrorKind::OutOfMemory => {}
+        // All stable variants are above and unstable in `_`
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    match VariantNonExhaustive::Baz(1, 2) {
+        VariantNonExhaustive::Baz(_, _) => {}
+        VariantNonExhaustive::Bar { x, .. } => {}
+    }
+    //~^^ some fields are not explicitly listed
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+    //~^ some fields are not explicitly listed
+
+    // Ok: this is local
+    #[warn(non_exhaustive_omitted_patterns)]
+    let Foo { a, b, .. } = Foo::default();
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+    //~^ some fields are not explicitly listed
+    //~^^ some fields are not explicitly listed
+
+    // Ok: because this only has 1 variant
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NonExhaustiveSingleVariant::A(true) {
+        NonExhaustiveSingleVariant::A(true) => {}
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NonExhaustiveSingleVariant::A(true) {
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    // Ok: we don't lint on `if let` expressions
+    #[deny(non_exhaustive_omitted_patterns)]
+    if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr
new file mode 100644 (file)
index 0000000..aebe2ac
--- /dev/null
@@ -0,0 +1,146 @@
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:127:9
+   |
+LL |         VariantNonExhaustive::Bar { x, .. } => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:124:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:132:9
+   |
+LL |     let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:131:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:140:29
+   |
+LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:139:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:140:9
+   |
+LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
+   |
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:54:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Struct { .. }` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:53:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:61:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Tuple(_)` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:60:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:71:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Unit` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:70:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:88:32
+   |
+LL |         NestedNonExhaustive::A(_) => {}
+   |                                ^ patterns `Tuple(_)` and `Struct { .. }` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:85:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:90:9
+   |
+LL |         _ => {}
+   |         ^ pattern `C` not covered
+   |
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:120:9
+   |
+LL |         _ => {}
+   |         ^ patterns `HostUnreachable`, `NetworkUnreachable`, `NetworkDown` and 18 more not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:97:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `ErrorKind` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:153:9
+   |
+LL |         _ => {}
+   |         ^ pattern `A(_)` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:151:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: aborting due to 7 previous errors; 4 warnings emitted
+
index b0c319f2c7f4188be632036d70463296597125d6..272b2ef6ee1d1c33e4ca036e16264c4805f795a5 100644 (file)
@@ -16,13 +16,13 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:11:24
+  ::: $DIR/auxiliary/structs.rs:12:24
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    |                        ---------------- a constructor is private if any of the fields is private
    |
 note: the tuple struct constructor `TupleStruct` is defined here
-  --> $DIR/auxiliary/structs.rs:11:1
+  --> $DIR/auxiliary/structs.rs:12:1
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
 note: the unit struct `UnitStruct` is defined here
-  --> $DIR/auxiliary/structs.rs:8:1
+  --> $DIR/auxiliary/structs.rs:9:1
    |
 LL | pub struct UnitStruct;
    | ^^^^^^^^^^^^^^^^^^^^^^
index 4514fd96c2eddc993490cfb7ec0e68d7e38ef102..593821bf96128acf0dc28d8186b392b7b196e5e7 100644 (file)
@@ -8,15 +8,15 @@ LL | trait Trait2015 { fn foo(#[allow(C)] i32); }
 help: if this is a `self` type, give it a parameter name
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
-   |                                      ~~~~~~~~~
+   |                                      +++++
 help: if this is a parameter name, give it a type
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
-   |                                      ~~~~~~~~~~~~~
+   |                                         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); }
-   |                                      ~~~~~~
+   |                                      ++
 
 error: aborting due to previous error
 
index 7185376b440c8fdf10e7b029f7f94f2a4ac1acba..cc24dbd96d2532ebc82c59a2e9fc4a7514891d86 100644 (file)
@@ -16,12 +16,17 @@ fn ne(&self, other: &S) -> bool {
 
 // 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 {
-// FIXME(fee1-dead)^ why should the order matter here?
-const fn equals_self<T: ~const PartialEq + PartialEq>(t: &T) -> bool {
+const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
     *t == *t
 }
 
-pub const EQ: bool = equals_self(&S);
+trait A: PartialEq {}
+impl<T: PartialEq> A for T {}
+
+const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S) && equals_self2(&S);
 
 fn main() {}
index 9b9bda7c90ec7d313aab8b9096411c4c5d6acc2f..0440f17a704deb18f88300aa614dd0c9d027240f 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: can't compare `S` with `S`
   --> $DIR/call-generic-method-nonconst.rs:19:34
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                                  ^^ no implementation for `S == S`
+   |                      ----------- ^^ no implementation for `S == S`
+   |                      |
+   |                      required by a bound introduced by this call
    |
    = help: the trait `PartialEq` is not implemented for `S`
 note: required by a bound in `equals_self`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
new file mode 100644 (file)
index 0000000..34cd1d2
--- /dev/null
@@ -0,0 +1,68 @@
+error: `~const` is not allowed here
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:45:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:47:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:1
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
new file mode 100644 (file)
index 0000000..3d4de08
--- /dev/null
@@ -0,0 +1,54 @@
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(const_fn_trait_bound)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::PhantomData;
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+    fn drop(&mut self) {
+        println!("Non trivial drop");
+    }
+}
+
+struct ConstImplWithDropGlue(NonTrivialDrop);
+
+impl const Drop for ConstImplWithDropGlue {
+    fn drop(&mut self) {}
+}
+
+trait A { fn a() { println!("A"); } }
+
+impl A for NonTrivialDrop {}
+
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+//~^ ERROR `~const` is not allowed
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+    fn drop(&mut self) {
+        T::a();
+    }
+}
+
+const fn check<T: ~const Drop>(_: T) {}
+
+macro_rules! check_all {
+    ($($exp:expr),*$(,)?) => {$(
+        const _: () = check($exp);
+    )*};
+}
+
+check_all! {
+    NonTrivialDrop,
+    //~^ ERROR the trait bound
+    ConstImplWithDropGlue(NonTrivialDrop),
+    //~^ ERROR the trait bound
+    ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+    //~^ ERROR the trait bound
+    //~| ERROR the trait bound
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
new file mode 100644 (file)
index 0000000..34cd1d2
--- /dev/null
@@ -0,0 +1,68 @@
+error: `~const` is not allowed here
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:45:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:47:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:1
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644 (file)
index 0000000..9a1b554
--- /dev/null
@@ -0,0 +1,81 @@
+// run-pass
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+#![feature(const_mut_refs)]
+#![feature(const_panic)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+const fn a<T: ~const Drop>(_: T) {}
+
+const fn b() -> u8 {
+    let mut c = 0;
+    let _ = S(&mut c);
+    a(S(&mut c));
+    c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+    ($($exp:expr),*$(,)?) => {
+        $(
+            const _: () = a($exp);
+        )*
+    }
+}
+
+#[allow(dead_code)]
+mod t {
+    pub struct Foo;
+    pub enum Bar { A }
+    pub fn foo() {}
+    pub struct ConstDrop;
+
+    impl const Drop for ConstDrop {
+        fn drop(&mut self) {}
+    }
+
+    pub struct HasConstDrop(pub ConstDrop);
+    pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+}
+
+use t::*;
+
+implements_const_drop! {
+    1u8,
+    2,
+    3.0,
+    Foo,
+    Bar::A,
+    foo,
+    ConstDrop,
+    HasConstDrop(ConstDrop),
+    TrivialFields(1, 2, 3, 4),
+    &1,
+    &1 as *const i32,
+}
+
+fn main() {
+    struct HasDropGlue(Box<u8>);
+    struct HasDropImpl;
+    impl Drop for HasDropImpl {
+        fn drop(&mut self) {
+            println!("not trivial drop");
+        }
+    }
+
+    // These types should pass because ~const in a non-const context should have no effect.
+    a(HasDropGlue(Box::new(0)));
+    a(HasDropImpl);
+
+    assert_eq!(C, 2);
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
new file mode 100644 (file)
index 0000000..fe1015b
--- /dev/null
@@ -0,0 +1,21 @@
+// check-pass
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+struct S;
+
+trait A {}
+trait B {}
+
+impl const A for S {}
+impl const B for S {}
+
+impl S {
+    const fn a<T: ~const A>() where T: ~const B {
+
+    }
+}
+
+const _: () = S::a::<S>();
+
+fn main() {}
index 81c0c4a78752313e925435f7632f8c2515d2d0f0..ea22d1c89b1cc38676067213af1b9f40dabbb0d0 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:24:10
    |
 LL |     call(foo);
-   |          ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+   |     ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -17,7 +19,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:25:14
    |
 LL |     call_mut(foo);
-   |              ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+   |     -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -32,7 +36,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:26:15
    |
 LL |     call_once(foo);
-   |               ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+   |     --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -47,7 +53,9 @@ error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:28:10
    |
 LL |     call(foo_unsafe);
-   |          ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     ---- ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
@@ -62,7 +70,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:30:14
    |
 LL |     call_mut(foo_unsafe);
-   |              ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     -------- ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
@@ -77,7 +87,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:32:15
    |
 LL |     call_once(foo_unsafe);
-   |               ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     --------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
index 4e2405504f0cb0b65bd4f7b5836dc63eaed15909..0aaaa7d47c3c1eef0bcf8066e2e08218136a495b 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 #[derive(Copy, Clone)]
 struct Foo {
index 7c16581686a00263de2456c7fb2f19b53a577571..932a435143b0c35bd5ba62f5804c40f82bdcee25 100644 (file)
@@ -33,7 +33,7 @@ LL |     let _: i32 = 22_i64 >> 1_i32;
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     let _: i32 = (22_i64 >> 1_i32).try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                  +               +++++++++++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs
new file mode 100644 (file)
index 0000000..9611780
--- /dev/null
@@ -0,0 +1,33 @@
+// build-fail
+
+// Test that the simd_shuffle intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct Simd<T, const N: usize>([T; N]);
+
+extern "platform-intrinsic" {
+    fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+fn main() {
+    const I: [u32; 2] = [0; 2];
+    const I2: [f32; 2] = [0.; 2];
+    let v = Simd::<u32, 4>([0; 4]);
+
+    unsafe {
+        let _: Simd<u32, 2> = simd_shuffle(v, v, I);
+
+        let _: Simd<u32, 4> = simd_shuffle(v, v, I);
+        //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+        let _: Simd<f32, 2> = simd_shuffle(v, v, I);
+        //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+        let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
+        //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+    }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr
new file mode 100644 (file)
index 0000000..9eeb000
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4_usize>` with length 4
+  --> $DIR/simd-intrinsic-generic-shuffle.rs:24:31
+   |
+LL |         let _: Simd<u32, 4> = simd_shuffle(v, v, I);
+   |                               ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4_usize>`), found `Simd<f32, 2_usize>` with element type `f32`
+  --> $DIR/simd-intrinsic-generic-shuffle.rs:27:31
+   |
+LL |         let _: Simd<f32, 2> = simd_shuffle(v, v, I);
+   |                               ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]`
+  --> $DIR/simd-intrinsic-generic-shuffle.rs:30:31
+   |
+LL |         let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
+   |                               ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd/monomorphize-shuffle-index.rs b/src/test/ui/simd/monomorphize-shuffle-index.rs
new file mode 100644 (file)
index 0000000..2467baa
--- /dev/null
@@ -0,0 +1,40 @@
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+trait Shuffle<const N: usize> {
+    const I: [u32; N];
+
+    unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N> {
+        simd_shuffle(a, b, Self::I)
+    }
+}
+
+fn main() {
+    struct I1;
+    impl Shuffle<4> for I1 {
+        const I: [u32; 4] = [0, 2, 4, 6];
+    }
+
+    struct I2;
+    impl Shuffle<2> for I2 {
+        const I: [u32; 2] = [1, 5];
+    }
+
+    let a = Simd::<u8, 4>([0, 1, 2, 3]);
+    let b = Simd::<u8, 4>([4, 5, 6, 7]);
+    unsafe {
+        let x: Simd<u8, 4> = I1.shuffle(a, b);
+        assert_eq!(x.0, [0, 2, 4, 6]);
+
+        let y: Simd<u8, 2> = I2.shuffle(a, b);
+        assert_eq!(y.0, [1, 5]);
+    }
+}
index 8a533453e75fdac4582bd294a131e09b63e6f674..aae6ce4663fbacd32705b45ff14c5578698ea50a 100644 (file)
@@ -188,4 +188,14 @@ fn main() {
          48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
          32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
          16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
+
+    extern "platform-intrinsic" {
+        fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+    }
+    let v = u8x2(0, 0);
+    const I: [u32; 2] = [4, 4];
+    unsafe {
+        let _: u8x2 = simd_shuffle(v, v, I);
+        //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+    }
 }
index 07253a4ae46bc44ad98bfdf796e62aea1858e460..737fb5e6e51e25c3f7f7cfb36a4294b5790e1f71 100644 (file)
@@ -71,6 +71,12 @@ LL | |          16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
    |
    = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 6 previous errors
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
+  --> $DIR/shuffle-not-out-of-bounds.rs:198:23
+   |
+LL |         let _: u8x2 = simd_shuffle(v, v, I);
+   |                       ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd/shuffle.rs b/src/test/ui/simd/shuffle.rs
new file mode 100644 (file)
index 0000000..3592adf
--- /dev/null
@@ -0,0 +1,24 @@
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+    const I1: [u32; 4] = [0, 2, 4, 6];
+    const I2: [u32; 2] = [1, 5];
+    let a = Simd::<u8, 4>([0, 1, 2, 3]);
+    let b = Simd::<u8, 4>([4, 5, 6, 7]);
+    unsafe {
+        let x: Simd<u8, 4> = simd_shuffle(a, b, I1);
+        assert_eq!(x.0, [0, 2, 4, 6]);
+
+        let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
+        assert_eq!(y.0, [1, 5]);
+    }
+}
index ab1fa2a4d87656b6702a1308258016f1d46cb5a6..0f630abd14876a5b21a0e00e40e1654270209403 100644 (file)
@@ -29,11 +29,17 @@ LL |     f.f.call_mut(())
 error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
    |
-LL |     let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
-   |         ----- captured outer variable
+LL |       let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
+   |           ----- captured outer variable
 ...
-LL |         foo(f);
-   |             ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
+LL |       f(Box::new(|a| {
+   |  ________________-
+LL | |
+LL | |         foo(f);
+   | |             ^ move occurs because `f` has type `[closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 54:6]`, which does not implement the `Copy` trait
+LL | |
+LL | |     }), 3);
+   | |_____- captured by this `FnMut` closure
 
 error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16
index da0a3c8b47602cc7ee57deb8839cbd4403a359dc..8d26ca4ac7a743096d8c0225dc73e07dffa32ddc 100644 (file)
@@ -8,11 +8,11 @@ LL | fn foo(Option<i32>, String) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn foo(self: Option<i32>, String) {}
-   |        ~~~~~~~~~~~~
+   |        +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(_: Option<i32>, String) {}
-   |        ~~~~~~~~~
+   |        ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/issue-34264.rs:1:27
@@ -24,11 +24,11 @@ LL | fn foo(Option<i32>, String) {}
 help: if this is a parameter name, give it a type
    |
 LL | fn foo(Option<i32>, String: TypeName) {}
-   |                     ~~~~~~~~~~~~~~~~
+   |                           ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(Option<i32>, _: String) {}
-   |                     ~~~~~~~~~
+   |                     ++
 
 error: expected one of `:`, `@`, or `|`, found `,`
   --> $DIR/issue-34264.rs:3:9
@@ -40,15 +40,15 @@ LL | fn bar(x, y: usize) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn bar(self: x, y: usize) {}
-   |        ~~~~~~~
+   |        +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn bar(x: TypeName, y: usize) {}
-   |        ~~~~~~~~~~~
+   |         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn bar(_: x, y: usize) {}
-   |        ~~~~
+   |        ++
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
diff --git a/src/test/ui/specialization/issue-35376.rs b/src/test/ui/specialization/issue-35376.rs
new file mode 100644 (file)
index 0000000..cc35213
--- /dev/null
@@ -0,0 +1,43 @@
+// check-pass
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+fn main() {}
+
+pub trait Alpha<T> { }
+
+pub trait Beta {
+    type Event;
+}
+
+pub trait Delta {
+    type Handle;
+    fn process(&self);
+}
+
+pub struct Parent<A, T>(A, T);
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+    type Handle = Handle;
+    default fn process(&self) {
+        unimplemented!()
+    }
+}
+
+impl<A, T> Delta for Parent<A, T>
+where A: Alpha<T::Handle> + Alpha<Handle>,
+      T: Delta,
+      T::Handle: Beta<Event = <Handle as Beta>::Event> {
+      fn process(&self) {
+        unimplemented!()
+      }
+}
+
+pub struct Handle;
+
+impl Beta for Handle {
+    type Event = ();
+}
diff --git a/src/test/ui/specialization/issue-35376.stderr b/src/test/ui/specialization/issue-35376.stderr
new file mode 100644 (file)
index 0000000..835277d
--- /dev/null
@@ -0,0 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-35376.rs:2: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
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/static/issue-34194.rs b/src/test/ui/static/issue-34194.rs
new file mode 100644 (file)
index 0000000..6dce556
--- /dev/null
@@ -0,0 +1,11 @@
+// build-pass
+#![allow(dead_code)]
+
+struct A {
+    a: &'static (),
+}
+
+static B: &'static A = &A { a: &() };
+static C: &'static A = &B;
+
+fn main() {}
index f323ba03c012cfd50753f64b43bd2b27fd72443d..47bd6f6bfa73d0158de9caf50e65c7c293f1fa15 100644 (file)
@@ -13,7 +13,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:4:19
    |
 LL |     let _ = s.get(4);
-   |                   ^ string indices are ranges of `usize`
+   |               --- ^ string indices are ranges of `usize`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
@@ -23,7 +25,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:5:29
    |
 LL |     let _ = s.get_unchecked(4);
-   |                             ^ string indices are ranges of `usize`
+   |               ------------- ^ string indices are ranges of `usize`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
index 3e49c8394ab0a06c4c685c0bdf2527428da3eb4b..ab647c75cf1205c88d919bf040775ff230c203a2 100644 (file)
@@ -37,7 +37,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:9:15
    |
 LL |     s.get_mut(1);
-   |               ^ string indices are ranges of `usize`
+   |       ------- ^ string indices are ranges of `usize`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
@@ -47,7 +49,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:11:25
    |
 LL |     s.get_unchecked_mut(1);
-   |                         ^ string indices are ranges of `usize`
+   |       ----------------- ^ string indices are ranges of `usize`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
index 55975cbdb5342ee491a78f37fe9d95017b9985f7..ca35a615d214774124cf33a6dd71f41dfe9186ad 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 trait noisy {
   fn speak(&mut self) -> isize;
index c9e98e21b9eb4411316b83cd75866ec8e27f13f2..732aa146ce446ee2e99161d5fa61290c624e75e5 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 trait noisy {
     fn speak(&mut self);
index 51c6b6d7e4ffe236994a6bec788cf33ec883dc7a..68ff73a0805921446b7c3b5ce9788857246218d4 100644 (file)
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 #[derive(Debug)]
 struct Foo {
     x: isize,
diff --git a/src/test/ui/structs-enums/issue-38002.rs b/src/test/ui/structs-enums/issue-38002.rs
new file mode 100644 (file)
index 0000000..fdb31fc
--- /dev/null
@@ -0,0 +1,35 @@
+// run-pass
+#![allow(dead_code)]
+// Check that constant ADTs are codegened OK, part k of N.
+
+enum Bar {
+    C
+}
+
+enum Foo {
+    A {},
+    B {
+        y: usize,
+        z: Bar
+    },
+}
+
+const LIST: [(usize, Foo); 2] = [
+    (51, Foo::B { y: 42, z: Bar::C }),
+    (52, Foo::B { y: 45, z: Bar::C }),
+];
+
+pub fn main() {
+    match LIST {
+        [
+            (51, Foo::B { y: 42, z: Bar::C }),
+            (52, Foo::B { y: 45, z: Bar::C })
+        ] => {}
+        _ => {
+            // I would want to print the enum here, but if
+            // the discriminant is garbage this causes an
+            // `unreachable` and silent process exit.
+            panic!("trivial match failed")
+        }
+    }
+}
index 87282ddbcca52d863b2275a344d4ff3ba474930c..ce599582378176d32670515d0c20643e644137ad 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 enum a_tag {
index 300c2a66c2996568af89bb03c6e33027ca839f46..78ebb3d6bfc245cebfe2b58aa8a040de58a158c4 100644 (file)
@@ -5,7 +5,9 @@ LL | async fn foo() {}
    |          --- consider calling this function
 ...
 LL |     bar(foo);
-   |         ^^^ `fn() -> impl Future {foo}` is not a future
+   |     --- ^^^ `fn() -> impl Future {foo}` is not a future
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}`
 note: required by a bound in `bar`
@@ -24,7 +26,9 @@ error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-be
 LL |     let async_closure = async || ();
    |                         -------- consider calling this closure
 LL |     bar(async_closure);
-   |         ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+   |     --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
 note: required by a bound in `bar`
index c50cbcde85553f43743b419998318f1a51588ced..fb1055c9c30931f9d307d13fb77aec747ceb2ece 100644 (file)
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:28:21
    |
-LL |     let x = X(Y);
-   |         - captured outer variable
+LL |       let x = X(Y);
+   |           - captured outer variable
 ...
-LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
-   |               |
-   |               data moved here
-   |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+   | |               --    ^ help: consider borrowing here: `&x`
+   | |               |
+   | |               data moved here
+   | |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:32:34
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
-   |                            |
-   |                            data moved here
-   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+LL | |
+LL | |         if let Either::One(_t) = e { }
+   | |                            --    ^ help: consider borrowing here: `&e`
+   | |                            |
+   | |                            data moved here
+   | |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:36:37
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
-   |                               |
-   |                               data moved here
-   |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         while let Either::One(_t) = e { }
+   | |                               --    ^ help: consider borrowing here: `&e`
+   | |                               |
+   | |                               data moved here
+   | |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:40:15
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
-...
-LL |             Either::One(_t)
-   |                         --
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match e {
+   | |               ^ help: consider borrowing here: `&e`
+...  |
+LL | |             Either::One(_t)
+   | |                         --
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:47:15
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
-...
-LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |             Either::One(_t) => (),
-   |                         --
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match e {
+   | |               ^ help: consider borrowing here: `&e`
+...  |
+LL | |             Either::One(_t) => (),
+   | |                         --
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:56:25
    |
-LL |     let x = X(Y);
-   |         - captured outer variable
+LL |       let x = X(Y);
+   |           - captured outer variable
 ...
-LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
-   |               |
-   |               data moved here
-   |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         let X(mut _t) = x;
+   | |               ------    ^ help: consider borrowing here: `&x`
+   | |               |
+   | |               data moved here
+   | |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:60:38
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
-   |                            |
-   |                            data moved here
-   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         if let Either::One(mut _t) = em { }
+   | |                            ------    ^^ help: consider borrowing here: `&em`
+   | |                            |
+   | |                            data moved here
+   | |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:64:41
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
-   |                               |
-   |                               data moved here
-   |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         while let Either::One(mut _t) = em { }
+   | |                               ------    ^^ help: consider borrowing here: `&em`
+   | |                               |
+   | |                               data moved here
+   | |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:68:15
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
-...
-LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |             Either::One(mut _t)
-   |                         ------
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match em {
+   | |               ^^ help: consider borrowing here: `&em`
+...  |
+LL | |             Either::One(mut _t)
+   | |                         ------
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `Fn` closure
   --> $DIR/move-into-closure.rs:75:15
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
-...
-LL |             Either::One(mut _t) => (),
-   |                         ------
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fn(|| {
+   |  ________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match em {
+   | |               ^^ help: consider borrowing here: `&em`
+...  |
+LL | |             Either::One(mut _t) => (),
+   | |                         ------
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `Fn` closure
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:95:21
    |
-LL |     let x = X(Y);
-   |         - captured outer variable
+LL |       let x = X(Y);
+   |           - captured outer variable
 ...
-LL |         let X(_t) = x;
-   |               --    ^ help: consider borrowing here: `&x`
-   |               |
-   |               data moved here
-   |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+   | |               --    ^ help: consider borrowing here: `&x`
+   | |               |
+   | |               data moved here
+   | |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:99:34
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         if let Either::One(_t) = e { }
-   |                            --    ^ help: consider borrowing here: `&e`
-   |                            |
-   |                            data moved here
-   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+LL | |
+LL | |         if let Either::One(_t) = e { }
+   | |                            --    ^ help: consider borrowing here: `&e`
+   | |                            |
+   | |                            data moved here
+   | |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:103:37
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         while let Either::One(_t) = e { }
-   |                               --    ^ help: consider borrowing here: `&e`
-   |                               |
-   |                               data moved here
-   |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         while let Either::One(_t) = e { }
+   | |                               --    ^ help: consider borrowing here: `&e`
+   | |                               |
+   | |                               data moved here
+   | |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:107:15
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
-...
-LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |             Either::One(_t)
-   |                         --
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match e {
+   | |               ^ help: consider borrowing here: `&e`
+...  |
+LL | |             Either::One(_t)
+   | |                         --
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `e.0`, as `e` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:114:15
    |
-LL |     let e = Either::One(X(Y));
-   |         - captured outer variable
+LL |       let e = Either::One(X(Y));
+   |           - captured outer variable
 ...
-LL |         match e {
-   |               ^ help: consider borrowing here: `&e`
-...
-LL |             Either::One(_t) => (),
-   |                         --
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match e {
+   | |               ^ help: consider borrowing here: `&e`
+...  |
+LL | |             Either::One(_t) => (),
+   | |                         --
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `x.0`, as `x` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:123:25
    |
-LL |     let x = X(Y);
-   |         - captured outer variable
+LL |       let x = X(Y);
+   |           - captured outer variable
 ...
-LL |         let X(mut _t) = x;
-   |               ------    ^ help: consider borrowing here: `&x`
-   |               |
-   |               data moved here
-   |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         let X(mut _t) = x;
+   | |               ------    ^ help: consider borrowing here: `&x`
+   | |               |
+   | |               data moved here
+   | |               move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:127:38
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         if let Either::One(mut _t) = em { }
-   |                            ------    ^^ help: consider borrowing here: `&em`
-   |                            |
-   |                            data moved here
-   |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         if let Either::One(mut _t) = em { }
+   | |                            ------    ^^ help: consider borrowing here: `&em`
+   | |                            |
+   | |                            data moved here
+   | |                            move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:131:41
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         while let Either::One(mut _t) = em { }
-   |                               ------    ^^ help: consider borrowing here: `&em`
-   |                               |
-   |                               data moved here
-   |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         while let Either::One(mut _t) = em { }
+   | |                               ------    ^^ help: consider borrowing here: `&em`
+   | |                               |
+   | |                               data moved here
+   | |                               move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:135:15
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
-...
-LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |             Either::One(mut _t)
-   |                         ------
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match em {
+   | |               ^^ help: consider borrowing here: `&em`
+...  |
+LL | |             Either::One(mut _t)
+   | |                         ------
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:142:15
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
-...
-LL |             Either::One(mut _t) => (),
-   |                         ------
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match em {
+   | |               ^^ help: consider borrowing here: `&em`
+...  |
+LL | |             Either::One(mut _t) => (),
+   | |                         ------
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `em.0`, as `em` is a captured variable in an `FnMut` closure
   --> $DIR/move-into-closure.rs:150:15
    |
-LL |     let mut em = Either::One(X(Y));
-   |         ------ captured outer variable
-...
-LL |         match em {
-   |               ^^ help: consider borrowing here: `&em`
+LL |       let mut em = Either::One(X(Y));
+   |           ------ captured outer variable
 ...
-LL |             Either::One(mut _t) => (),
-   |                         ------
-   |                         |
-   |                         data moved here
-   |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+LL |       consume_fnmut(|| {
+   |  ___________________-
+LL | |         let X(_t) = x;
+LL | |
+LL | |
+...  |
+LL | |         match em {
+   | |               ^^ help: consider borrowing here: `&em`
+...  |
+LL | |             Either::One(mut _t) => (),
+   | |                         ------
+   | |                         |
+   | |                         data moved here
+   | |                         move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+...  |
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error: aborting due to 21 previous errors
 
index 93048107e59fcfd82d1820ae5622f8c8222decd9..b111df49f6e5396c20e6d7ec2c2c49d09164a844 100644 (file)
@@ -5,7 +5,9 @@ LL | fn foo() -> impl T<O=()> { S }
    |    --- consider calling this function
 ...
 LL |     bar(foo);
-   |         ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
@@ -23,7 +25,9 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou
 LL |     let closure = || S;
    |                   -- consider calling this closure
 LL |     bar(closure);
-   |         ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+   |     --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
index 39bde52c55a59ea038f02be5f0a62723871f2903..71779ecb7299f1f14bd0a2cc609a6dc73127bdc0 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:12:7
    |
 LL |   foo(&s);
-   |       ^^ the trait `Trait` is not implemented for `&S`
+   |   --- ^^ the trait `Trait` is not implemented for `&S`
+   |   |
+   |   required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <&'a mut S as Trait>
@@ -20,10 +22,11 @@ error[E0277]: the trait bound `S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:13:7
    |
 LL |   foo(s);
-   |       ^
-   |       |
-   |       expected an implementor of trait `Trait`
-   |       help: consider mutably borrowing here: `&mut s`
+   |   --- ^
+   |   |   |
+   |   |   expected an implementor of trait `Trait`
+   |   |   help: consider mutably borrowing here: `&mut s`
+   |   required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/imm-ref-trait-object-literal.rs:7:11
index bb7919ebb7996338108f03caa21f05031f67647d..229c4b824f27578726d12947fb1474e77c0ae3f4 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:14:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -19,7 +21,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:22:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -36,7 +40,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:30:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -53,7 +59,9 @@ error[E0277]: `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't impl
   --> $DIR/impl-trait-with-missing-bounds.rs:37:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator + std::fmt::Debug as Iterator>::Item`
 note: required by a bound in `qux`
@@ -70,7 +78,9 @@ 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`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -87,7 +97,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:45:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
index b2be09a4c7f5db89ad91e06077ea99cb02b55e99..93251b2c8dbfc62d91d8102b74300dec54412d43 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
   --> $DIR/issue-62843.rs:4:32
    |
 LL |     println!("{:?}", line.find(pattern));
-   |                                ^^^^^^^
-   |                                |
-   |                                expected an implementor of trait `Pattern<'_>`
-   |                                help: consider borrowing here: `&pattern`
+   |                           ---- ^^^^^^^
+   |                           |    |
+   |                           |    expected an implementor of trait `Pattern<'_>`
+   |                           |    help: consider borrowing here: `&pattern`
+   |                           required by a bound introduced by this call
    |
    = note: the trait bound `String: Pattern<'_>` is not satisfied
    = note: required because of the requirements on the impl of `Pattern<'_>` for `String`
index 009707a3a6449489969728fb1a21b00e39fe6e23..c3418dab0e8afb7309bc875ba0ff7b92876a2797 100644 (file)
@@ -8,11 +8,11 @@ LL | pub fn foo(Box<Self>) { }
 help: if this is a `self` type, give it a parameter name
    |
 LL | pub fn foo(self: Box<Self>) { }
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | pub fn foo(_: Box<Self>) { }
-   |            ~~~~~~
+   |            ++
 
 error: expected one of `:`, `@`, or `|`, found `<`
   --> $DIR/issue-64252-self-type.rs:10:15
@@ -24,11 +24,11 @@ LL |     fn bar(Box<Self>) { }
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn bar(self: Box<Self>) { }
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar(_: Box<Self>) { }
-   |            ~~~~~~
+   |            ++
 
 error: aborting due to 2 previous errors
 
index cd1a8c4be8eccd6ee6651e3cf2b08814f6d3bd08..a3ab0b8efb060860d1a4e41672c2cd1d586bf5a2 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
   --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20
    |
 LL |     assert_is_send(&bar);
-   |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
 note: required by a bound in `assert_is_send`
@@ -19,7 +21,9 @@ error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
   --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20
    |
 LL |     assert_is_send(&bar);
-   |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
 note: required by a bound in `assert_is_send`
index df1eeb7a2b898a816765705bf53acd0ac3af3cc3..c1a7a2e101d62476c8951efb94d3cd1d9201bf71 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-2.rs:11:9
    |
 LL |     foo(a);
-   |         ^
-   |         |
-   |         expected an implementor of trait `Tr`
-   |         help: consider mutably borrowing here: `&mut a`
+   |     --- ^
+   |     |   |
+   |     |   expected an implementor of trait `Tr`
+   |     |   help: consider mutably borrowing here: `&mut a`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-84973-2.rs:7:11
index db954530b1bebe34acb5cb34ac2de3a2146e5880..6813b07a2ee64069483b5919d7d583d94cc10de1 100644 (file)
@@ -21,7 +21,6 @@ fn main() {
     let ref_cl: &dyn Fn() -> () = &cl;
     f_sized(*ref_cl);
     //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
-    //~| ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
 
     use std::rc::Rc;
     let rc = Rc::new(0);
index 2ffe2f5a2b688eb006ffec9d3937776e5ac3c435..ae55c96702adaed6e9fd46b0482a968834e5d53c 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/issue-84973-blacklist.rs:15:12
    |
 LL |     f_copy("".to_string());
-   |            ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f_copy`
   --> $DIR/issue-84973-blacklist.rs:6:14
@@ -14,7 +16,9 @@ error[E0277]: the trait bound `S: Clone` is not satisfied
   --> $DIR/issue-84973-blacklist.rs:16:13
    |
 LL |     f_clone(S);
-   |             ^ the trait `Clone` is not implemented for `S`
+   |     ------- ^ the trait `Clone` is not implemented for `S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f_clone`
   --> $DIR/issue-84973-blacklist.rs:7:15
@@ -39,7 +43,9 @@ error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilat
   --> $DIR/issue-84973-blacklist.rs:22:13
    |
 LL |     f_sized(*ref_cl);
-   |             ^^^^^^^ doesn't have a size known at compile-time
+   |     ------- ^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `dyn Fn()`
 note: required by a bound in `f_sized`
@@ -49,10 +55,12 @@ LL | fn f_sized<T: Sized>(t: T) {}
    |            ^ required by this bound in `f_sized`
 
 error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
-  --> $DIR/issue-84973-blacklist.rs:28:12
+  --> $DIR/issue-84973-blacklist.rs:27:12
    |
 LL |     f_send(rc);
-   |            ^^ `Rc<{integer}>` cannot be sent between threads safely
+   |     ------ ^^ `Rc<{integer}>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Rc<{integer}>`
 note: required by a bound in `f_send`
@@ -61,16 +69,6 @@ note: required by a bound in `f_send`
 LL | fn f_send<T: Send>(t: T) {}
    |              ^^^^ required by this bound in `f_send`
 
-error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time
-  --> $DIR/issue-84973-blacklist.rs:22:5
-   |
-LL |     f_sized(*ref_cl);
-   |     ^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Fn()`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
index bd1cf6ba61460784357a382a85012243caeae8cf..14b32d8515cd78c82029d5559b79dc693cac2cf9 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:10:9
    |
 LL |     bar(a);
-   |         ^ the trait `Tr` is not implemented for `i32`
+   |     --- ^ the trait `Tr` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/issue-84973-negative.rs:5:11
@@ -14,10 +16,11 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:11:9
    |
 LL |     bar(b);
-   |         ^
-   |         |
-   |         expected an implementor of trait `Tr`
-   |         help: consider borrowing here: `&b`
+   |     --- ^
+   |     |   |
+   |     |   expected an implementor of trait `Tr`
+   |     |   help: consider borrowing here: `&b`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/issue-84973-negative.rs:5:11
index 649517b7d99da6c8cffb3d78e81e8ee8c836df19..169d0cccb43efe05e0c3df6e8f4e75d19489a961 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
   --> $DIR/issue-84973.rs:6:24
    |
 LL |     let o = Other::new(f);
-   |                        ^
-   |                        |
-   |                        expected an implementor of trait `SomeTrait`
-   |                        help: consider borrowing here: `&f`
+   |             ---------- ^
+   |             |          |
+   |             |          expected an implementor of trait `SomeTrait`
+   |             |          help: consider borrowing here: `&f`
+   |             required by a bound introduced by this call
    |
 note: required by `Other::<'a, G>::new`
   --> $DIR/issue-84973.rs:27:5
index 3b71d5cee93905fef82baa17191aa4a62cdc4c82..e6a2231390076e02c059bd0b26959f54af4c97ab 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
   --> $DIR/mut-borrow-needed-by-trait.rs:17:29
    |
 LL |     let fp = BufWriter::new(fp);
-   |                             ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |              -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |              |
+   |              required by a bound introduced by this call
    |
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by `BufWriter::<W>::new`
index f332b7213d8bcc6e5b13b6721308bca4383af306..54f19fe9da445bc476004b244b5c1e8950e4f753 100644 (file)
@@ -4,8 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | fn bar(x: &dyn Trait) {}
    |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `baz` to another trait
-   = help: consider moving `bat` 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-unsafe-trait-references-self.rs:2:22
    |
@@ -15,6 +13,8 @@ LL |     fn baz(&self, _: Self) {}
    |                      ^^^^ ...because method `baz` references the `Self` type in this parameter
 LL |     fn bat(&self) -> Self {}
    |                      ^^^^ ...because method `bat` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
+   = help: consider moving `bat` to another trait
 
 error[E0038]: the trait `Other` cannot be made into an object
   --> $DIR/object-unsafe-trait-references-self.rs:10:12
index cfbee1518cd69f72b66487f5689b01f1ff9664d4..a0ce7d05b4d48efecc2aa29787f701d344254ba9 100644 (file)
@@ -1,17 +1,22 @@
 error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure
   --> $DIR/option-content-move2.rs:9:9
    |
-LL |     let mut var = None;
-   |         ------- captured outer variable
-...
-LL |         move || {
-   |         ^^^^^^^ move out of `var` occurs here
-LL |
-LL |             var = Some(NotCopyable);
-   |             ---
-   |             |
-   |             move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
-   |             move occurs due to use in closure
+LL |       let mut var = None;
+   |           ------- captured outer variable
+LL |       func(|| {
+   |  __________-
+LL | |         // Shouldn't suggest `move ||.as_ref()` here
+LL | |         move || {
+   | |         ^^^^^^^ move out of `var` occurs here
+LL | |
+LL | |             var = Some(NotCopyable);
+   | |             ---
+   | |             |
+   | |             move occurs because `var` has type `Option<NotCopyable>`, which does not implement the `Copy` trait
+   | |             move occurs due to use in closure
+LL | |         }
+LL | |     });
+   | |_____- captured by this `FnMut` closure
 
 error: aborting due to previous error
 
index b62502fb6a2b13779aac2675bd19da886ddf73ed..551a7c5060fc743e9b677ab3a67d63e0954e3fa0 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `impl Sync` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:4:13
    |
 LL |     is_send(val);
-   |             ^^^ `impl Sync` cannot be sent between threads safely
+   |     ------- ^^^ `impl Sync` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -18,7 +20,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:8:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -34,7 +38,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:12:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -50,7 +56,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:20:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -66,7 +74,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:24:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -82,7 +92,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:28:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs
new file mode 100644 (file)
index 0000000..ecb7f54
--- /dev/null
@@ -0,0 +1,16 @@
+fn main() {
+  let v = vec![1i32, 2, 3];
+  for _ in v[1..] {
+    //~^ ERROR [i32]` is not an iterator [E0277]
+    //~^^ ERROR known at compilation time
+  }
+  struct K {
+    n: i32,
+  }
+  let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }];
+  for i2 in v2[1..] {
+    //~^ ERROR [K]` is not an iterator [E0277]
+    //~^^ ERROR known at compilation time
+    i2.n = 2;
+  }
+}
diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr
new file mode 100644 (file)
index 0000000..018f62e
--- /dev/null
@@ -0,0 +1,71 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/slice-issue-87994.rs:3:12
+   |
+LL |   for _ in v[1..] {
+   |            ^^^^^^
+   |            |
+   |            expected an implementor of trait `IntoIterator`
+   |            help: consider borrowing here: `&v[1..]`
+   |
+   = note: the trait bound `[i32]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[i32]` is not an iterator
+  --> $DIR/slice-issue-87994.rs:3:12
+   |
+LL |   for _ in v[1..] {
+   |            ^^^^^^
+   |            |
+   |            expected an implementor of trait `IntoIterator`
+   |            help: consider borrowing here: `&v[1..]`
+   |
+   = note: the trait bound `[i32]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+  --> $DIR/slice-issue-87994.rs:11:13
+   |
+LL |   for i2 in v2[1..] {
+   |             ^^^^^^^
+   |             |
+   |             expected an implementor of trait `IntoIterator`
+   |             help: consider borrowing here: `&v2[1..]`
+   |
+   = note: the trait bound `[K]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[K]` is not an iterator
+  --> $DIR/slice-issue-87994.rs:11:13
+   |
+LL |   for i2 in v2[1..] {
+   |             ^^^^^^^
+   |             |
+   |             expected an implementor of trait `IntoIterator`
+   |             help: consider borrowing here: `&v2[1..]`
+   |
+   = note: the trait bound `[K]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
index 1f14ebae84127220c5e692af00cf2c399a7decc4..8dfab8dfa17e5bc1b50b1ab4df1d84cd1721f5ba 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&T: std::io::Read` is not satisfied
   --> $DIR/suggest-change-mut.rs:12:48
    |
 LL |         let mut stream_reader = BufReader::new(&stream);
-   |                                                ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+   |                                 -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+   |                                 |
+   |                                 required by a bound introduced by this call
    |
 note: required by `BufReader::<R>::new`
   --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
index b391cd4beb47925138299a7aa554b8bc6b2e1ad4..12466868f002872f88114c172c241f12fdf1c8b5 100644 (file)
@@ -2,19 +2,23 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
    |
 LL |     let _ = RGB { r, g, c };
-   |                   ^
-   |                   |
-   |                   expected `f64`, found `f32`
-   |                   help: you can convert an `f32` to an `f64`: `r: r.into()`
+   |                   ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r: r.into(), g, c };
+   |                   ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
    |
 LL |     let _ = RGB { r, g, c };
-   |                      ^
-   |                      |
-   |                      expected `f64`, found `f32`
-   |                      help: you can convert an `f32` to an `f64`: `g: g.into()`
+   |                      ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g: g.into(), c };
+   |                      ++  +++++++
 
 error[E0560]: struct `RGB` has no field named `c`
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
index 61ea852a8c462b061a1c85fbc9ce5cfbcbdc25de..72c84d167167fc69b2ab6177ae02b06441d8deaa 100644 (file)
@@ -2,28 +2,34 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
    |
 LL |     let _ = RGB { r, g, b };
-   |                   ^
-   |                   |
-   |                   expected `f64`, found `f32`
-   |                   help: you can convert an `f32` to an `f64`: `r: r.into()`
+   |                   ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r: r.into(), g, b };
+   |                   ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
    |
 LL |     let _ = RGB { r, g, b };
-   |                      ^
-   |                      |
-   |                      expected `f64`, found `f32`
-   |                      help: you can convert an `f32` to an `f64`: `g: g.into()`
+   |                      ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g: g.into(), b };
+   |                      ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
    |
 LL |     let _ = RGB { r, g, b };
-   |                         ^
-   |                         |
-   |                         expected `f64`, found `f32`
-   |                         help: you can convert an `f32` to an `f64`: `b: b.into()`
+   |                         ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g, b: b.into() };
+   |                         ++  +++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/symbol-names/issue-53912.rs b/src/test/ui/symbol-names/issue-53912.rs
new file mode 100644 (file)
index 0000000..65b6825
--- /dev/null
@@ -0,0 +1,37 @@
+// build-pass
+
+// This test is the same code as in ui/symbol-names/issue-60925.rs but this checks that the
+// reproduction compiles successfully and doesn't segfault, whereas that test just checks that the
+// symbol mangling fix produces the correct result.
+
+fn dummy() {}
+
+mod llvm {
+    pub(crate) struct Foo;
+}
+mod foo {
+    pub(crate) struct Foo<T>(T);
+
+    impl Foo<::llvm::Foo> {
+        pub(crate) fn foo() {
+            for _ in 0..0 {
+                for _ in &[::dummy()] {
+                    ::dummy();
+                    ::dummy();
+                    ::dummy();
+                }
+            }
+        }
+    }
+
+    pub(crate) fn foo() {
+        Foo::foo();
+        Foo::foo();
+    }
+}
+
+pub fn foo() {
+    foo::foo();
+}
+
+fn main() {}
index 422aa904e1d934692fe2288af4bf338f76354f39..10dfd2de744fc0f383d17c053a9dfd3c947df4e9 100644 (file)
@@ -9,7 +9,7 @@ LL | fn f() -> isize { return g(); }
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL | fn f() -> isize { return g().try_into().unwrap(); }
-   |                          ~~~~~~~~~~~~~~~~~~~~~~~
+   |                             ++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/test-attrs/issue-36768.rs b/src/test/ui/test-attrs/issue-36768.rs
new file mode 100644 (file)
index 0000000..f671cbc
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags:--test
+#![deny(private_in_public)]
+
+#[test] fn foo() {}
+mod foo {}
+
+#[test] fn core() {}
+extern crate core;
diff --git a/src/test/ui/thread-local/tls.rs b/src/test/ui/thread-local/tls.rs
new file mode 100644 (file)
index 0000000..fbd3413
--- /dev/null
@@ -0,0 +1,14 @@
+// run-pass
+// ignore-emscripten no threads support
+// compile-flags: -O
+
+#![feature(thread_local)]
+
+#[thread_local]
+static S: u32 = 222;
+
+fn main() {
+    let local = &S as *const u32 as usize;
+    let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
+    assert_ne!(local, foreign);
+}
diff --git a/src/test/ui/tls.rs b/src/test/ui/tls.rs
deleted file mode 100644 (file)
index fbd3413..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// run-pass
-// ignore-emscripten no threads support
-// compile-flags: -O
-
-#![feature(thread_local)]
-
-#[thread_local]
-static S: u32 = 222;
-
-fn main() {
-    let local = &S as *const u32 as usize;
-    let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
-    assert_ne!(local, foreign);
-}
index 15f5fe16bc7bbcdb0d16ca164222c8fb1e39f2b8..81e5589d6eb3536e2787c4f32f38ff4447acb623 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied
   --> $DIR/same-crate-name.rs:31:20
    |
 LL |         a::try_foo(foo);
-   |                    ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+   |         ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: trait impl with same name found
   --> $DIR/auxiliary/crate_a2.rs:5:1
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satis
   --> $DIR/same-crate-name.rs:38:20
    |
 LL |         a::try_foo(implements_no_traits);
-   |                    ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `try_foo`
   --> $DIR/auxiliary/crate_a1.rs:3:24
@@ -32,7 +36,9 @@ error[E0277]: the trait bound `ImplementsWrongTraitConditionally<isize>: main::a
   --> $DIR/same-crate-name.rs:45:20
    |
 LL |         a::try_foo(other_variant_implements_mismatched_trait);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: trait impl with same name found
   --> $DIR/auxiliary/crate_a2.rs:13:1
@@ -50,7 +56,9 @@ error[E0277]: the trait bound `ImplementsTraitForUsize<isize>: main::a::Bar` is
   --> $DIR/same-crate-name.rs:51:20
    |
 LL |         a::try_foo(other_variant_implements_correct_trait);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <ImplementsTraitForUsize<usize> as main::a::Bar>
diff --git a/src/test/ui/traits/bug-7183-generics.rs b/src/test/ui/traits/bug-7183-generics.rs
new file mode 100644 (file)
index 0000000..f53a173
--- /dev/null
@@ -0,0 +1,36 @@
+// run-pass
+
+trait Speak : Sized {
+    fn say(&self, s:&str) -> String;
+    fn hi(&self) -> String { hello(self) }
+}
+
+fn hello<S:Speak>(s:&S) -> String{
+    s.say("hello")
+}
+
+impl Speak for isize {
+    fn say(&self, s:&str) -> String {
+        format!("{}: {}", s, *self)
+    }
+}
+
+impl<T: Speak> Speak for Option<T> {
+    fn say(&self, s:&str) -> String {
+        match *self {
+            None => format!("{} - none", s),
+            Some(ref x) => { format!("something!{}", x.say(s)) }
+        }
+    }
+}
+
+
+pub fn main() {
+    assert_eq!(3.hi(), "hello: 3".to_string());
+    assert_eq!(Some(Some(3)).hi(),
+               "something!something!hello: 3".to_string());
+    assert_eq!(None::<isize>.hi(), "hello - none".to_string());
+
+    assert_eq!(Some(None::<isize>).hi(), "something!hello - none".to_string());
+    assert_eq!(Some(3).hi(), "something!hello: 3".to_string());
+}
index 5206b5721063a5c1539a59d7942f3617b4e4a63a..7895e50eef5c428e211dd00a54d897f546901ce0 100644 (file)
@@ -10,7 +10,9 @@ error[E0277]: the trait bound `NoClone: Copy` is not satisfied
   --> $DIR/supertrait-auto-trait.rs:16:23
    |
 LL |     let (a, b) = copy(NoClone);
-   |                       ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+   |                  ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+   |                  |
+   |                  required by a bound introduced by this call
    |
    = note: required because of the requirements on the impl of `Magic` for `NoClone`
 note: required by a bound in `copy`
diff --git a/src/test/ui/traits/issue-20692.rs b/src/test/ui/traits/issue-20692.rs
new file mode 100644 (file)
index 0000000..1cb2d8c
--- /dev/null
@@ -0,0 +1,11 @@
+trait Array: Sized + Copy {}
+
+fn f<T: Array>(x: &T) {
+    let _ = x
+    //~^ ERROR `Array` cannot be made into an object
+    as
+    &dyn Array;
+    //~^ ERROR `Array` cannot be made into an object
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-20692.stderr b/src/test/ui/traits/issue-20692.stderr
new file mode 100644 (file)
index 0000000..1d7f252
--- /dev/null
@@ -0,0 +1,35 @@
+error[E0038]: the trait `Array` cannot be made into an object
+  --> $DIR/issue-20692.rs:7:5
+   |
+LL |     &dyn Array;
+   |     ^^^^^^^^^^ `Array` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-20692.rs:1:14
+   |
+LL | trait Array: Sized + Copy {}
+   |       -----  ^^^^^   ^^^^ ...because it requires `Self: Sized`
+   |       |      |
+   |       |      ...because it requires `Self: Sized`
+   |       this trait cannot be made into an object...
+
+error[E0038]: the trait `Array` cannot be made into an object
+  --> $DIR/issue-20692.rs:4:13
+   |
+LL |     let _ = x
+   |             ^ `Array` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/issue-20692.rs:1:14
+   |
+LL | trait Array: Sized + Copy {}
+   |       -----  ^^^^^   ^^^^ ...because it requires `Self: Sized`
+   |       |      |
+   |       |      ...because it requires `Self: Sized`
+   |       this trait cannot be made into an object...
+   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Array>` for `&T`
+   = note: required by cast to type `&dyn Array`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/issue-23825.rs b/src/test/ui/traits/issue-23825.rs
new file mode 100644 (file)
index 0000000..a9f0095
--- /dev/null
@@ -0,0 +1,21 @@
+// run-pass
+trait Stringify {
+    fn to_string(&self) -> String;
+}
+
+impl Stringify for u32 {
+    fn to_string(&self) -> String { format!("u32: {}", *self) }
+}
+
+impl Stringify for f32 {
+    fn to_string(&self) -> String { format!("f32: {}", *self) }
+}
+
+fn print<T: Stringify>(x: T) -> String {
+    x.to_string()
+}
+
+fn main() {
+    assert_eq!(&print(5), "u32: 5");
+    assert_eq!(&print(5.0), "f32: 5");
+}
index 2260dcfc70ea38f4d4eff58a6ca91234fba9d67a..ef5d5cdff8f4b14f2d4df31bd715af7d70e71444 100644 (file)
@@ -127,9 +127,6 @@ error[E0038]: the trait `assoc_const::C` cannot be made into an object
 LL |     <dyn C>::A;
    |      ^^^^^ `assoc_const::C` cannot be made into an object
    |
-   = help: consider moving `C` to another trait
-   = help: consider moving `B` to another trait
-   = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/item-privacy.rs:25:15
    |
@@ -143,6 +140,9 @@ LL |     pub trait C: A + B {
    |               - this trait cannot be made into an object...
 LL |         const C: u8 = 0;
    |               ^ ...because it contains this associated `const`
+   = help: consider moving `C` to another trait
+   = help: consider moving `A` to another trait
+   = help: consider moving `B` to another trait
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:115:12
index ccdace1957d39a209f7a648f7dd8625010636891..6caa23d8f4997ef4e97a81f31ab69b98d52cafef 100644 (file)
@@ -7,7 +7,7 @@ LL |     test(22i32, 44i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     test(22i32, 44u32);
-   |                 ~~~~~
+   |                   ~~~
 
 error: aborting due to previous error
 
index ad95e06eb4e521ae0bee0e586ac5374045a908cb..790e2a81c3a8c0efcdd5ffa6b76b301b866b29b0 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:23:11
    |
 LL |     Outer(TestType);
-   |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |     ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `dummy::TestType`
 note: required by `Outer`
@@ -28,7 +30,9 @@ error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:32:13
    |
 LL |     is_send(TestType);
-   |             ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `dummy1b::TestType`
 note: required by a bound in `is_send`
@@ -41,9 +45,11 @@ error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:40:13
    |
 LL |     is_send((8, TestType));
-   |             ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
+   = help: the trait `Send` is not implemented for `dummy1c::TestType`
    = note: required because it appears within the type `({integer}, dummy1c::TestType)`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -55,10 +61,11 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:48:13
    |
 LL |     is_send(Box::new(TestType));
-   |             ^^^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Send`
-   |             help: consider borrowing here: `&Box::new(TestType)`
+   |     ------- ^^^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Send`
+   |     |       help: consider borrowing here: `&Box::new(TestType)`
+   |     required by a bound introduced by this call
    |
    = note: the trait bound `dummy2::TestType: Send` is not satisfied
    = note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
@@ -73,9 +80,11 @@ error[E0277]: `dummy3::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:56:13
    |
 LL |     is_send(Box::new(Outer2(TestType)));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
+   = help: the trait `Send` is not implemented for `dummy3::TestType`
 note: required because it appears within the type `Outer2<dummy3::TestType>`
   --> $DIR/negated-auto-traits-error.rs:12:8
    |
@@ -93,10 +102,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:66:13
    |
 LL |     is_sync(Outer2(TestType));
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Sync`
-   |             help: consider borrowing here: `&Outer2(TestType)`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Sync`
+   |     |       help: consider borrowing here: `&Outer2(TestType)`
+   |     required by a bound introduced by this call
    |
    = note: the trait bound `main::TestType: Sync` is not satisfied
 note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
index 526c0e9ed540fa3485fbe1d8726246bdc19f87d8..e7d1ee616b34f731f4dfe5bd7e6c54d6d85ffba2 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): MyTrait` is not satisfied
   --> $DIR/no-use.rs:10:26
    |
 LL |     <() as MyTrait>::foo(&());
-   |                          ^^^ the trait `MyTrait` is not implemented for `()`
+   |     -------------------- ^^^ the trait `MyTrait` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <() as MyTrait>
index 10eeec20d98d761c1a6ee07385fdcfa79b17227d..2c225f4311d017fd5a72f65dec9f0702b7c02dea 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
   --> $DIR/issue-39029.rs:16:37
    |
 LL |     let _errors = TcpListener::bind(&bad);
-   |                                     ^^^^
-   |                                     |
-   |                                     the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
-   |                                     help: consider adding dereference here: `&*bad`
+   |                   ----------------- ^^^^
+   |                   |                 |
+   |                   |                 the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+   |                   |                 help: consider adding dereference here: `&*bad`
+   |                   required by a bound introduced by this call
    |
    = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
index 750c8a86c56ddd5a387defc4380efb63d344f0d0..b77af7ddf474628863341ce536372d48bbed572e 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied
   --> $DIR/issue-62530.rs:13:26
    |
 LL |     takes_type_parameter(&string);  // Error
-   |                          ^^^^^^^
-   |                          |
-   |                          the trait `SomeTrait` is not implemented for `&String`
-   |                          help: consider adding dereference here: `&*string`
+   |     -------------------- ^^^^^^^
+   |     |                    |
+   |     |                    the trait `SomeTrait` is not implemented for `&String`
+   |     |                    help: consider adding dereference here: `&*string`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_type_parameter`
   --> $DIR/issue-62530.rs:4:44
index 6fcf8780d6e225c1cac761d4a133bcea5e38d184..bf9f85f1b4595ec4d2c541145af0b83ffd637068 100644 (file)
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied
   --> $DIR/multiple-0.rs:34:9
    |
 LL |     foo(&baz);
-   |         ^^^^
-   |         |
-   |         the trait `Happy` is not implemented for `&Baz`
-   |         help: consider adding dereference here: `&***baz`
+   |     --- ^^^^
+   |     |   |
+   |     |   the trait `Happy` is not implemented for `&Baz`
+   |     |   help: consider adding dereference here: `&***baz`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/multiple-0.rs:30:26
index 268f375050a4c8c618068e02be60854a2ce6742e..040fbb3e3e699813fae132946c7076eddfcd92d2 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied
   --> $DIR/multiple-1.rs:52:9
    |
 LL |     foo(&mut baz);
-   |         ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+   |     --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/multiple-1.rs:45:26
index 0289424510f9781cebb0e0ecc267897e5d9ad9ab..d943b48fd0082115045e051a5f884cf56b545fe3 100644 (file)
@@ -32,8 +32,6 @@ error[E0038]: the trait `bar` cannot be made into an object
 LL |     (box 10 as Box<dyn bar>).dup();
    |                ^^^^^^^^^^^^ `bar` cannot be made into an object
    |
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` 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/test-2.rs:4:30
    |
@@ -42,6 +40,8 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       |                      |
    |       |                      ...because method `dup` references the `Self` type in its return type
    |       this trait cannot be made into an object...
+   = help: consider moving `dup` to another trait
+   = help: consider moving `blah` to another trait
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:6
@@ -49,8 +49,6 @@ error[E0038]: the trait `bar` cannot be made into an object
 LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ `bar` cannot be made into an object
    |
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` 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/test-2.rs:4:30
    |
@@ -59,6 +57,8 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       |                      |
    |       |                      ...because method `dup` references the `Self` type in its return type
    |       this trait cannot be made into an object...
+   = help: consider moving `dup` to another trait
+   = help: consider moving `blah` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
    = note: required by cast to type `Box<dyn bar>`
 
index 6508e6a6e767fdad2c234faedde8ce8165fac0cd..26679e713803e01925e4b37ff394fff69b7deb33 100644 (file)
@@ -10,7 +10,7 @@ LL |     B::get_x()
 help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     B::get_x().try_into().unwrap()
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error: aborting due to previous error
 
index 97ef2dd37f7910f2f6ab3ce0155899e0e4fb8563..d9e0d21541edefaa2ac7cd83cdde96bf95bfe68f 100644 (file)
@@ -24,7 +24,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:25:15
    |
 LL |     Foo::test(&4i32);
-   |               ^^^^^ the trait `Foo` is not implemented for `i32`
+   |     --------- ^^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `Foo::test`
   --> $DIR/trivial-bounds-leak.rs:5:5
@@ -36,7 +38,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:26:22
    |
 LL |     generic_function(5i32);
-   |                      ^^^^ the trait `Foo` is not implemented for `i32`
+   |     ---------------- ^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `generic_function`
   --> $DIR/trivial-bounds-leak.rs:29:24
index c5a2405462932dad56d491348e71c97f63c38e0e..d8dd31645e06162f37987f06b87d04fc2a3a4773 100644 (file)
@@ -2,43 +2,71 @@ warning: unnecessary parentheses around function argument
   --> $DIR/try-block-unused-delims.rs:11:13
    |
 LL |     consume((try {}));
-   |             ^^^^^^^^ help: remove these parentheses
+   |             ^      ^
    |
 note: the lint level is defined here
   --> $DIR/try-block-unused-delims.rs:6:9
    |
 LL | #![warn(unused_parens, unused_braces)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     consume((try {}));
+LL +     consume(try {});
+   | 
 
 warning: unnecessary braces around function argument
   --> $DIR/try-block-unused-delims.rs:14:13
    |
 LL |     consume({ try {} });
-   |             ^^^^^^^^^^ help: remove these braces
+   |             ^^      ^^
    |
 note: the lint level is defined here
   --> $DIR/try-block-unused-delims.rs:6:24
    |
 LL | #![warn(unused_parens, unused_braces)]
    |                        ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     consume({ try {} });
+LL +     consume(try {});
+   | 
 
 warning: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:17:11
    |
 LL |     match (try {}) {
-   |           ^^^^^^^^ help: remove these parentheses
+   |           ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     match (try {}) {
+LL +     match try {} {
+   | 
 
 warning: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:22:22
    |
 LL |     if let Err(()) = (try {}) {}
-   |                      ^^^^^^^^ help: remove these parentheses
+   |                      ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     if let Err(()) = (try {}) {}
+LL +     if let Err(()) = try {} {}
+   | 
 
 warning: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:25:11
    |
 LL |     match (try {}) {
-   |           ^^^^^^^^ help: remove these parentheses
+   |           ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     match (try {}) {
+LL +     match try {} {
+   | 
 
 warning: 5 warnings emitted
 
index ac1027ff34a131d47b0cb248a30ec5646f2fbdfa..fbfbffbd24e2ff79892d16733d827015a408355a 100644 (file)
@@ -2,10 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:9:18
    |
 LL |     identity_u16(x);
-   |                  ^
-   |                  |
-   |                  expected `u16`, found `u8`
-   |                  help: you can convert a `u8` to a `u16`: `x.into()`
+   |                  ^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     identity_u16(x.into());
+   |                   +++++++
 
 error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:12:18
@@ -16,7 +18,7 @@ LL |     identity_u16(y);
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     identity_u16(y.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:21:18
@@ -27,7 +29,7 @@ LL |     identity_u16(a);
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     identity_u16(a.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs
new file mode 100644 (file)
index 0000000..e50cc58
--- /dev/null
@@ -0,0 +1,12 @@
+macro_rules! many_args {
+    ([$($t:tt)*]#$($h:tt)*) => {
+        many_args!{[$($t)*$($t)*]$($h)*}
+    };
+    ([$($t:tt)*]) => {
+        fn _f($($t: ()),*) {} //~ ERROR function can not have more than 65535 arguments
+    }
+}
+
+many_args!{[_]########## ######}
+
+fn main() {}
diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr
new file mode 100644 (file)
index 0000000..615fd2c
--- /dev/null
@@ -0,0 +1,13 @@
+error: function can not have more than 65535 arguments
+  --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:24
+   |
+LL |           fn _f($($t: ()),*) {}
+   |  ________________________^
+LL | |     }
+LL | | }
+LL | |
+LL | | many_args!{[_]########## ######}
+   | |____________^
+
+error: aborting due to previous error
+
index 2de5f6eb0f03aa25ed69a9d7971d3248bc1d201a..8a296dc7ee6e12506d7c5f12cd1f4d7507886786 100644 (file)
@@ -16,7 +16,6 @@ error[E0038]: the trait `MyAdd` cannot be made into an object
 LL |     let y = x as dyn MyAdd<i32>;
    |                  ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object
    |
-   = help: consider moving `add` 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/type-parameter-defaults-referencing-Self-ppaux.rs:6:55
    |
@@ -24,6 +23,7 @@ LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
    |       -----                                           ^^^^ ...because method `add` references the `Self` type in its return type
    |       |
    |       this trait cannot be made into an object...
+   = help: consider moving `add` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.fixed b/src/test/ui/typeck/issue-88803-call-expr-method.fixed
new file mode 100644 (file)
index 0000000..19b96ec
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        a.unwrap() //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs
new file mode 100644 (file)
index 0000000..a061994
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        (a.unwrap)() //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr
new file mode 100644 (file)
index 0000000..dd717ed
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>`
+  --> $DIR/issue-88803-call-expr-method.rs:7:12
+   |
+LL |         (a.unwrap)()
+   |            ^^^^^^ method, not a field
+   |
+help: remove wrapping parentheses to call the method
+   |
+LL -         (a.unwrap)()
+LL +         a.unwrap()
+   | 
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/typeck/issue-88844.rs b/src/test/ui/typeck/issue-88844.rs
new file mode 100644 (file)
index 0000000..116c75a
--- /dev/null
@@ -0,0 +1,14 @@
+// Regression test for #88844.
+
+struct Struct { value: i32 }
+//~^ NOTE: similarly named struct `Struct` defined here
+
+impl Stuct {
+//~^ ERROR: cannot find type `Stuct` in this scope [E0412]
+//~| HELP: a struct with a similar name exists
+    fn new() -> Self {
+        Self { value: 42 }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/issue-88844.stderr b/src/test/ui/typeck/issue-88844.stderr
new file mode 100644 (file)
index 0000000..90bba90
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0412]: cannot find type `Stuct` in this scope
+  --> $DIR/issue-88844.rs:6:6
+   |
+LL | struct Struct { value: i32 }
+   | ------------- similarly named struct `Struct` defined here
+...
+LL | impl Stuct {
+   |      ^^^^^ help: a struct with a similar name exists: `Struct`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed b/src/test/ui/typeck/issue-89044-wrapped-expr-method.fixed
new file mode 100644 (file)
index 0000000..0a3086a
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        (a.unwrap()) //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs b/src/test/ui/typeck/issue-89044-wrapped-expr-method.rs
new file mode 100644 (file)
index 0000000..83617e0
--- /dev/null
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        (a.unwrap) //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr b/src/test/ui/typeck/issue-89044-wrapped-expr-method.stderr
new file mode 100644 (file)
index 0000000..6fa0915
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>`
+  --> $DIR/issue-89044-wrapped-expr-method.rs:7:12
+   |
+LL |         (a.unwrap)
+   |            ^^^^^^ method, not a field
+   |
+help: use parentheses to call the method
+   |
+LL |         (a.unwrap())
+   |                  ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
index c0f388bd15b28a46d8b9fe635d0aeb61d9a3417a..4b5804253b23b7efa555e35ce0ff0601eab5bc97 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: `UnsafeCell<MySync<{integer}>>` cannot be shared between threads s
   --> $DIR/typeck-unsafe-always-share.rs:19:10
    |
 LL |     test(us);
-   |          ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+   |     ---- ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `UnsafeCell<MySync<{integer}>>`
 note: required by a bound in `test`
@@ -15,7 +17,9 @@ error[E0277]: `UnsafeCell<NoSync>` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:23:10
    |
 LL |     test(uns);
-   |          ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     ---- ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `UnsafeCell<NoSync>`
 note: required by a bound in `test`
@@ -46,7 +50,9 @@ error[E0277]: `NoSync` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:30:10
    |
 LL |     test(NoSync);
-   |          ^^^^^^ `NoSync` cannot be shared between threads safely
+   |     ---- ^^^^^^ `NoSync` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `NoSync`
 note: required by a bound in `test`
index 5c58e29fa0027b36251a78d3e49c8c06cddf0869..e82b5e4497383fd5cd9b28f8ded4e955b35ff715 100644 (file)
@@ -15,7 +15,7 @@ LL |     let b: typeof(a) = 1i8;
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |     let b: typeof(a) = 1u8;
-   |                        ~~~
+   |                         ~~
 
 error: aborting due to 2 previous errors
 
index 8dc024697d7fc6fb77b8f473a252f1bc9af431f8..23b9157375657fba56ba004e252df3b55d53c377 100644 (file)
@@ -20,7 +20,7 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
-   |                            ~~~~
+   |                             ~~~
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
@@ -31,7 +31,7 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
-   |                               ~~~~
+   |                                ~~~
 
 error: aborting due to 3 previous errors
 
index f8c90176ff134dac28211ed7eb80b74985f0600c..482d3e44fe4ea7f0656ff49342c76ddb0e1c8905 100644 (file)
@@ -4,7 +4,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
 LL |         let x = Box::new(0);
    |             - captured outer variable
 LL |         let f = to_fn(|| drop(x));
-   |                               ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                       --------^-
+   |                       |       |
+   |                       |       move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                       captured by this `Fn` closure
 
 error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:19:35
@@ -12,7 +15,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
 LL |         let x = Box::new(0);
    |             - captured outer variable
 LL |         let f = to_fn_mut(|| drop(x));
-   |                                   ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                           --------^-
+   |                           |       |
+   |                           |       move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                           captured by this `FnMut` closure
 
 error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
   --> $DIR/unboxed-closure-illegal-move.rs:28:36
@@ -20,7 +26,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
 LL |         let x = Box::new(0);
    |             - captured outer variable
 LL |         let f = to_fn(move || drop(x));
-   |                                    ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                       -------------^-
+   |                       |            |
+   |                       |            move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                       captured by this `Fn` closure
 
 error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:32:40
@@ -28,7 +37,10 @@ error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
 LL |         let x = Box::new(0);
    |             - captured outer variable
 LL |         let f = to_fn_mut(move || drop(x));
-   |                                        ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                           -------------^-
+   |                           |            |
+   |                           |            move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+   |                           captured by this `FnMut` closure
 
 error: aborting due to 4 previous errors
 
index f30bf40983e23cfe74790311632f332682d8568d..c8ce3091cf611f54d71be90a106296a2f9afc3ce 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `S`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21
    |
 LL |     let x = call_it(&S, 22);
-   |                     ^^ expected an `Fn<(isize,)>` closure, found `S`
+   |             ------- ^^ expected an `Fn<(isize,)>` closure, found `S`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Fn<(isize,)>` is not implemented for `S`
 note: required by a bound in `call_it`
index 67bf4be54e621412cf9de4279f2531ce8d4d9fc1..f791ea62ceb65f50ca68d90891bb18aebbc68bce 100644 (file)
@@ -7,7 +7,7 @@ LL |     let z = f(1_usize, 2);
 help: change the type of the numeric literal from `usize` to `isize`
    |
 LL |     let z = f(1_isize, 2);
-   |               ~~~~~~~
+   |                 ~~~~~
 
 error: aborting due to previous error
 
index 6b21b9246f7afd20dc3e4c8fa02e5a87a53ca379..c9a20232f3508891f71b2e47d4afdcbe80c08783 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r i
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
index 936cb27759aad7e2a271a0659b05799c1a71d11e..77c176de625ca95e456b7d3af0dd3a7b3e631b7e 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&
   --> $DIR/unboxed-closures-wrong-abi.rs:20:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> extern "C" f
   --> $DIR/unboxed-closures-wrong-abi.rs:25:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> extern "C"
   --> $DIR/unboxed-closures-wrong-abi.rs:30:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
index f9f1182e30998a63def1cee27e7209fc384f3f4f..64d57773d70810ccec4703af0df870e999938150 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isi
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `unsafe fn(isize) ->
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) ->
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it_once`
diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.rs b/src/test/ui/unnamed_fields/restrict_anonymous.rs
deleted file mode 100644 (file)
index 99637d1..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#![allow(incomplete_features)]
-#![feature(unnamed_fields)]
-
-fn f() -> struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-fn f2(a: struct { field: u8 } ) {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-union G {
-    field: struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-}
-//~| ERROR unions may not contain fields that need dropping [E0740]
-
-struct H { _: u8 } // Should error after hir checks
-
-struct I(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-enum J {
-    K(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-    L {
-        _ : struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-        //~^ ERROR anonymous fields are not allowed outside of structs or unions
-        //~| ERROR anonymous structs are unimplemented
-    },
-    M {
-        _ : u8 //~ ERROR anonymous fields are not allowed outside of structs or unions
-    }
-}
-
-static M: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-type N = union { field: u8 }; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-fn main() {
-    const O: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let p: [struct { field: u8 }; 1]; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let q: (struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let cl = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-}
diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.stderr b/src/test/ui/unnamed_fields/restrict_anonymous.stderr
deleted file mode 100644 (file)
index efcf544..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:4:11
-   |
-LL | fn f() -> struct { field: u8 } {}
-   |           ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:7:10
-   |
-LL | fn f2(a: struct { field: u8 } ) {}
-   |          ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:11:12
-   |
-LL |     field: struct { field: u8 }
-   |            ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:18:10
-   |
-LL | struct I(struct { field: u8 }, u8);
-   |          ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:22:7
-   |
-LL |     K(struct { field: u8 }),
-   |       ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
-  --> $DIR/restrict_anonymous.rs:25:9
-   |
-LL |         _ : struct { field: u8 }
-   |         -^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         anonymous field declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:25:13
-   |
-LL |         _ : struct { field: u8 }
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
-  --> $DIR/restrict_anonymous.rs:30:9
-   |
-LL |         _ : u8
-   |         -^^^^^
-   |         |
-   |         anonymous field declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:34:11
-   |
-LL | static M: union { field: u8 } = 0;
-   |           ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:37:10
-   |
-LL | type N = union { field: u8 };
-   |          ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:41:14
-   |
-LL |     const O: struct { field: u8 } = 0;
-   |              ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:44:13
-   |
-LL |     let p: [struct { field: u8 }; 1];
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:47:13
-   |
-LL |     let q: (struct { field: u8 }, u8);
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:50:20
-   |
-LL |     let cl = || -> struct { field: u8 } {};
-   |                    ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:4:11
-   |
-LL | fn f() -> struct { field: u8 } {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:7:10
-   |
-LL | fn f2(a: struct { field: u8 } ) {}
-   |          ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:11:12
-   |
-LL |     field: struct { field: u8 }
-   |            ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:18:10
-   |
-LL | struct I(struct { field: u8 }, u8);
-   |          ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:22:7
-   |
-LL |     K(struct { field: u8 }),
-   |       ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:25:13
-   |
-LL |         _ : struct { field: u8 }
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
-  --> $DIR/restrict_anonymous.rs:34:11
-   |
-LL | static M: union { field: u8 } = 0;
-   |           ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
-  --> $DIR/restrict_anonymous.rs:37:10
-   |
-LL | type N = union { field: u8 };
-   |          ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:44:13
-   |
-LL |     let p: [struct { field: u8 }; 1];
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:47:13
-   |
-LL |     let q: (struct { field: u8 }, u8);
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:50:20
-   |
-LL |     let cl = || -> struct { field: u8 } {};
-   |                    ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:41:14
-   |
-LL |     const O: struct { field: u8 } = 0;
-   |              ^^^^^^^^^^^^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/restrict_anonymous.rs:11:5
-   |
-LL |     field: struct { field: u8 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/restrict_anonymous.rs:11:5
-   |
-LL |     field: struct { field: u8 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr
new file mode 100644 (file)
index 0000000..9e9cbcf
--- /dev/null
@@ -0,0 +1,35 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         let f = |v: &mut Vec<_>| {
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+   |
+LL | #[deny(unused_unsafe)]
+   |        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |                 |w: &mut Vec<u32>| { unsafe {
+   |                                      ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             |x: &mut Vec<u32>| { unsafe {
+   |                                  ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs
new file mode 100644 (file)
index 0000000..ac1cfd6
--- /dev/null
@@ -0,0 +1,28 @@
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#[deny(unused_unsafe)]
+fn main() {
+    let mut v = Vec::<i32>::with_capacity(24);
+
+    unsafe {
+        let f = |v: &mut Vec<_>| {
+            unsafe { //~ ERROR unnecessary `unsafe`
+                v.set_len(24);
+                |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+                    w.set_len(32);
+                } };
+            }
+            |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+                x.set_len(40);
+            } };
+        };
+
+        v.set_len(0);
+        f(&mut v);
+    }
+
+    |y: &mut Vec<u32>| { unsafe {
+        y.set_len(48);
+    } };
+}
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr
new file mode 100644 (file)
index 0000000..9e9cbcf
--- /dev/null
@@ -0,0 +1,35 @@
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         let f = |v: &mut Vec<_>| {
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+   |
+LL | #[deny(unused_unsafe)]
+   |        ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |                 |w: &mut Vec<u32>| { unsafe {
+   |                                      ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+...
+LL |             |x: &mut Vec<u32>| { unsafe {
+   |                                  ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
index a7f57e3fd15667d81396d6c40e1293565bde5a18..6686e55130fb453579d774d736238a9282612281 100644 (file)
@@ -12,9 +12,11 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/unsized-exprs.rs:24:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
-   |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+   = help: the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
   --> $DIR/unsized-exprs.rs:3:8
    |
index f5b5d02593155963477ca07a306c15b9bd305550..39b6583bc4ec4123d915ad1372e47022b1c6973e 100644 (file)
@@ -44,8 +44,6 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
 fn f10<X: ?Sized>(x1: Box<S<X>>) {
     f5(&(32, *x1));
     //~^ ERROR the size for values of type
-    //~| ERROR the size for values of type
 }
 
-pub fn main() {
-}
+pub fn main() {}
index f7bb6c9c78c65ef4141e3e1b7adeebc3d44ceeff..ae89f2f997728cc2de862b0cca3517d81bdedc03 100644 (file)
@@ -4,7 +4,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f1<X: ?Sized>(x: &X) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f2::<X>(x);
-   |             ^ doesn't have a size known at compile-time
+   |     ------- ^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f2`
   --> $DIR/unsized3.rs:10:7
@@ -27,7 +29,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f3<X: ?Sized + T>(x: &X) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f4::<X>(x);
-   |             ^ doesn't have a size known at compile-time
+   |     ------- ^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f4`
   --> $DIR/unsized3.rs:21:7
@@ -50,7 +54,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(x1);
-   |        ^^ doesn't have a size known at compile-time
+   |     -- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -78,7 +84,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(*x1, 34));
-   |        ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -92,34 +100,15 @@ LL - fn f9<X: ?Sized>(x1: Box<S<X>>) {
 LL + fn f9<X>(x1: Box<S<X>>) {
    | 
 
-error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized3.rs:45:9
-   |
-LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
-   |        - this type parameter needs to be `std::marker::Sized`
-LL |     f5(&(32, *x1));
-   |         ^^^^^^^^^ doesn't have a size known at compile-time
-   |
-note: required because it appears within the type `S<X>`
-  --> $DIR/unsized3.rs:28:8
-   |
-LL | struct S<X: ?Sized> {
-   |        ^
-   = note: required because it appears within the type `({integer}, S<X>)`
-   = note: tuples must have a statically known size to be initialized
-help: consider removing the `?Sized` bound to make the type parameter `Sized`
-   |
-LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
-LL + fn f10<X>(x1: Box<S<X>>) {
-   | 
-
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:45:8
    |
 LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
    |        - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(32, *x1));
-   |        ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -127,21 +116,13 @@ note: required because it appears within the type `S<X>`
 LL | struct S<X: ?Sized> {
    |        ^
    = note: required because it appears within the type `({integer}, S<X>)`
-note: required by a bound in `f5`
-  --> $DIR/unsized3.rs:24:7
-   |
-LL | fn f5<Y>(x: &Y) {}
-   |       ^ required by this bound in `f5`
+   = note: tuples must have a statically known size to be initialized
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
 LL + fn f10<X>(x1: Box<S<X>>) {
    | 
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn f5<Y: ?Sized>(x: &Y) {}
-   |        ++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
deleted file mode 100644 (file)
index eccb315..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-struct A;
-
-impl A {
-//~^ NOTE `Self` type implicitly declared here, by this `impl`
-    fn banana(&mut self) {
-        fn peach(this: &Self) {
-        //~^ ERROR can't use generic parameters from outer function
-        //~| NOTE use of generic parameter from outer function
-        //~| NOTE use a type here instead
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
deleted file mode 100644 (file)
index 9660934..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/use-self-in-inner-fn.rs:6:25
-   |
-LL | impl A {
-   | ---- `Self` type implicitly declared here, by this `impl`
-...
-LL |         fn peach(this: &Self) {
-   |                         ^^^^
-   |                         |
-   |                         use of generic parameter from outer function
-   |                         use a type here instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
index bff64813268ce687c4011d776077aed30a0e1878..c5fff622b6b232941913ef93fe33ee2fa67a3fd1 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `{integer}: TraitA` is not satisfied
   --> $DIR/vtable-res-trait-param.rs:17:18
    |
 LL |     b.gimme_an_a(y)
-   |                  ^ the trait `TraitA` is not implemented for `{integer}`
+   |       ---------- ^ the trait `TraitA` is not implemented for `{integer}`
+   |       |
+   |       required by a bound introduced by this call
 
 error: aborting due to previous error
 
index 010200b5ded1f40faf3355bf3b6e09b834c152f9..c924cd87997e137a864a6e5cc73d37b983e1743b 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `T` cannot be made into an object
 LL |     const CONST: (bool, dyn T);
    |                         ^^^^^ `T` cannot be made into an object
    |
-   = help: consider moving `CONST` 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/issue-87495.rs:4:11
    |
@@ -12,6 +11,7 @@ LL | trait T {
    |       - this trait cannot be made into an object...
 LL |     const CONST: (bool, dyn T);
    |           ^^^^^ ...because it contains this associated `const`
+   = help: consider moving `CONST` to another trait
 
 error: aborting due to previous error
 
index 9b749f88fb810e173271052f63cddd6118da9771..64969fbe3203e0af8fdbccb7c85968c92f9e7a97 100644 (file)
@@ -4,7 +4,6 @@ error[E0038]: the trait `A` cannot be made into an object
 LL |     let _x: &dyn A;
    |             ^^^^^^ `A` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/wf-object-safe.rs:5:23
    |
@@ -12,6 +11,7 @@ LL | trait A {
    |       - this trait cannot be made into an object...
 LL |     fn foo(&self, _x: &Self);
    |                       ^^^^^ ...because method `foo` references the `Self` type in this parameter
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
index 0df5f91c8f3f1e0b157e7c32950658044b35c542..43fbc0a9061cff74b220d25f6a5dd3f65440acc7 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22
    |
 LL |         require_copy(self.x);
-   |                      ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `require_copy`
   --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20
index 97d651e0bec9fa9e8e5254f321989fe2f7f1bd3d..f2db8fcc4a3f5e13f1ce9616ef73492e55ab790c 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22
    |
 LL |         require_copy(self.x);
-   |                      ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `require_copy`
   --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20
index d7de83104c1dee2ce60f22dba35f149a56e4829c..3223dca3cddbfdb86e2c255e98c2068fd1fe8477 100644 (file)
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Bar: Eq` is not satisfied
   --> $DIR/where-clauses-method-unsatisfied.rs:18:14
    |
 LL |     x.equals(&x);
-   |              ^^ the trait `Eq` is not implemented for `Bar`
+   |       ------ ^^ the trait `Eq` is not implemented for `Bar`
+   |       |
+   |       required by a bound introduced by this call
 
 error: aborting due to previous error
 
index 8e240a0e40d475f01263263760f203e8aefbf5fd..c686a0b2f5aeaa4572b8d1847ea8995802d78f67 100644 (file)
@@ -9,7 +9,7 @@ LL | fn mk_int() -> usize { let i: isize = 3; return i; }
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
-   |                                                 ~~~~~~~~~~~~~~~~~~~~~
+   |                                                  ++++++++++++++++++++
 
 error: aborting due to previous error
 
index 334407c2b2e56d32d773bc105e32ced7a39626df..340acff34f2ab76fd47e23f6a1792a37a95d500b 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "build-manifest"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 toml = "0.5"
index ab63a9e2dfa0b8b7b39211e0ca96c52d17101212..c1579ae9ac54a225a57ae865bda8bc6416ee957b 100644 (file)
@@ -99,6 +99,7 @@
     "i686-unknown-freebsd",
     "i686-unknown-linux-gnu",
     "i686-unknown-linux-musl",
+    "m68k-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
     "mips64-unknown-linux-gnuabi64",
index 7d64e20a3d360e95298189fd5e3f0b6d6b702ae5..cf8840ff6ee8918c2f05094be17ac6ea9433dfb9 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "bump-stage0"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
index 18751dd3f238d94d384a7fe967abfac06cbfe0b9..9a28ac83c9eb73e42ffafac552c0a55f00dbf40c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 18751dd3f238d94d384a7fe967abfac06cbfe0b9
+Subproject commit 9a28ac83c9eb73e42ffafac552c0a55f00dbf40c
index a88272d234456e193af1c3c1d11cd5dc0ac0dc9a..bfd894e2bd27b2f2e57e104bba7c8ab3ee39e194 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "cargotest2"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [[bin]]
 name = "cargotest"
index 2310370fb9fbe7eaed80f888f40633a2f8151fd3..40aaa5924df5b391862f379c8fd159920f5b061d 100644 (file)
@@ -21,37 +21,35 @@ name = "clippy-driver"
 path = "src/driver.rs"
 
 [dependencies]
-# begin automatic update
-clippy_lints = { version = "0.1.50", path = "clippy_lints" }
-# end automatic update
+clippy_lints = { version = "0.1", path = "clippy_lints" }
 semver = "0.11"
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
-tempfile = { version = "3.1.0", optional = true }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
+tempfile = { version = "3.2", optional = true }
 
 [dev-dependencies]
 cargo_metadata = "0.12"
-compiletest_rs = { version = "0.6.0", features = ["tmp"] }
+compiletest_rs = { version = "0.7", features = ["tmp"] }
 tester = "0.9"
-regex = "1.4"
+regex = "1.5"
 # This is used by the `collect-metadata` alias.
 filetime = "0.2"
 
 # A noop dependency that changes in the Rust repository, it's a bit of a hack.
 # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
 # for more information.
-rustc-workspace-hack = "1.0.0"
+rustc-workspace-hack = "1.0"
 
 # UI test dependencies
 clippy_utils = { path = "clippy_utils" }
 derive-new = "0.5"
 if_chain = "1.0"
-itertools = "0.10.1"
-quote = "1"
+itertools = "0.10"
+quote = "1.0"
 serde = { version = "1.0", features = ["derive"] }
-syn = { version = "1", features = ["full"] }
+syn = { version = "1.0", features = ["full"] }
 
 [build-dependencies]
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
 
 [features]
 deny-warnings = ["clippy_lints/deny-warnings"]
index 0fae8c7b9afcfbf47778d814f47815d9391d7d89..d7d2655026b4bc941ea2d54bf219bc173e091083 100644 (file)
@@ -6,11 +6,11 @@ edition = "2018"
 [dependencies]
 bytecount = "0.6"
 clap = "2.33"
-itertools = "0.9"
+itertools = "0.10"
 opener = "0.5"
-regex = "1"
+regex = "1.5"
 shell-escape = "0.1"
-walkdir = "2"
+walkdir = "2.3"
 
 [features]
 deny-warnings = []
index a1707bad5c2680bf266a59284aa26e4c6ffad368..c206a1eb07b500a28c114936e7a27af2879cd3a0 100644 (file)
@@ -13,4 +13,4 @@ keywords = ["clippy", "lint", "plugin"]
 categories = ["development-tools", "development-tools::cargo-plugins"]
 
 [build-dependencies]
-term = "0.6"
+term = "0.7"
index 3c28024bf926a4e1243ce0d52910223d28da0562..e59175a55e184e9eaedfaecd76c79580c4d55383 100644 (file)
@@ -11,21 +11,21 @@ edition = "2018"
 [dependencies]
 cargo_metadata = "0.12"
 clippy_utils = { path = "../clippy_utils" }
-if_chain = "1.0.0"
-itertools = "0.9"
+if_chain = "1.0"
+itertools = "0.10"
 pulldown-cmark = { version = "0.8", default-features = false }
-quine-mc_cluskey = "0.2.2"
+quine-mc_cluskey = "0.2"
 regex-syntax = "0.6"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
-toml = "0.5.3"
+toml = "0.5"
 unicode-normalization = "0.1"
-unicode-script = { version = "0.5.3", default-features = false }
+unicode-script = { version = "0.5", default-features = false }
 semver = "0.11"
-rustc-semver = "1.1.0"
+rustc-semver = "1.1"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
-url = { version = "2.1.0", features = ["serde"] }
+url = { version = "2.2", features = ["serde"] }
 
 [features]
 deny-warnings = ["clippy_utils/deny-warnings"]
index c9ff468874b58e953b66dfd03c65204b3cfeb010..2ef7dcc1775a6bfe9d6bf2d6784389c7839ff993 100644 (file)
@@ -527,8 +527,8 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
                 return;
             }
 
-            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt());
-            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt());
+            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
+            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent());
 
             if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
                 let lines = snippet.split('\n').collect::<Vec<_>>();
index bd5426ba707a8b2624dd4ed905c9a0f9b25ec063..162911b77d6153b6f02fc7b8d6e5ada56fcfe2a1 100644 (file)
@@ -1,7 +1,5 @@
 //! lint on missing cargo common metadata
 
-use std::path::PathBuf;
-
 use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
@@ -69,12 +67,8 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel
     span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
 }
 
-fn is_empty_str(value: &Option<String>) -> bool {
-    value.as_ref().map_or(true, String::is_empty)
-}
-
-fn is_empty_path(value: &Option<PathBuf>) -> bool {
-    value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
+fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
+    value.as_ref().map_or(true, |s| s.as_ref().is_empty())
 }
 
 fn is_empty_vec(value: &[String]) -> bool {
@@ -98,7 +92,7 @@ fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
                     missing_warning(cx, &package, "package.description");
                 }
 
-                if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
+                if is_empty_str(&package.license) && is_empty_str(&package.license_file) {
                     missing_warning(cx, &package, "either package.license or package.license_file");
                 }
 
@@ -106,7 +100,7 @@ fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
                     missing_warning(cx, &package, "package.repository");
                 }
 
-                if is_empty_path(&package.readme) {
+                if is_empty_str(&package.readme) {
                     missing_warning(cx, &package, "package.readme");
                 }
 
index 96c30d57ee198c54d2b6688ec84bbc7e8a5e8ed5..2203d1c39f1793e6c517b7db92f3baf19c6d691f 100644 (file)
@@ -95,7 +95,7 @@ fn check<'tcx>(
                     });
 
                     if let Some((low, high)) = pos {
-                        Span::new(low, high, header_span.ctxt())
+                        Span::new(low, high, header_span.ctxt(), header_span.parent())
                     } else {
                         return;
                     }
index d58e49491203c1da290327d0af845d72d2018024..6ded2f233efea615f800800a41ffd3fda50a563a 100644 (file)
@@ -472,7 +472,7 @@ fn emit_branches_sharing_code_lint(
 
         let mut span = moved_start.to(span_end);
         // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
-        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt());
+        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
         if snippet_opt(cx, test_span)
             .map(|snip| snip == "    ")
             .unwrap_or_default()
index cb2b7f5be70addb065d7efb2196ec96290275fd2..0b61909ddd82d5f7df7a29342aad3eaeabf2a893 100644 (file)
@@ -665,6 +665,7 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
             span.lo() + BytePos::from_usize(offset),
             span.lo() + BytePos::from_usize(offset + word.len()),
             span.ctxt(),
+            span.parent(),
         );
 
         check_word(cx, word, span);
index 7e4d1b3ef9f0d78365391ada01d0c3e81492024b..f22f52b949e1a8609bb55be59bac866544a02758 100644 (file)
@@ -65,7 +65,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
     }
 }
 
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) {
+fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
     use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
     use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath};
 
index 6b407c7bb6724b5d288ab5dbb61d2af55960c941..2fe32fcf6651a8b67420a4fc798d8b2326f9aba4 100644 (file)
@@ -130,7 +130,7 @@ fn suggestion<'tcx>(
                         let pos = snippet_opt(cx, item.span.until(target.span()))
                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
                         if let Some(pos) = pos {
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         } else {
                             return;
                         }
@@ -173,7 +173,7 @@ fn suggestion<'tcx>(
                                     Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
                                 })
                                 .expect("failed to create span for type parameters");
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         });
 
                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
index 10281496c11cbb4e65887c6ea5e17447d17a2ab3..fe6814e35d0ca1da4475f6428eb0c3fcd8186ec9 100644 (file)
@@ -63,6 +63,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
                     hi_pos - BytePos::from_usize("const".len()),
                     hi_pos,
                     item.span.ctxt(),
+                    item.span.parent(),
                 );
                 span_lint_and_then(
                     cx,
index 68bef2f4c8bbb351e808dcd6c78193e8896a5bc6..12ffe7a136457d67219c83c78a2f443cae616b6b 100644 (file)
@@ -15,7 +15,6 @@ pub(super) fn check<'tcx>(
     pat: &'tcx Pat<'_>,
     arg: &'tcx Expr<'_>,
     body: &'tcx Expr<'_>,
-    expr: &'tcx Expr<'_>,
 ) {
     let pat_span = pat.span;
 
@@ -43,7 +42,7 @@ pub(super) fn check<'tcx>(
                 span_lint_and_then(
                     cx,
                     FOR_KV_MAP,
-                    expr.span,
+                    arg_span,
                     &format!("you seem to want to iterate on a map's {}s", kind),
                     |diag| {
                         let map = sugg::Sugg::hir(cx, arg, "map");
index 9148fbfd497af3e1c4de607ff583296135995e35..e640c62ebdaceabc102d798869f804e7a1d203b0 100644 (file)
@@ -5,12 +5,12 @@
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
     if is_trait_method(cx, arg, sym::Iterator) {
         span_lint(
             cx,
             ITER_NEXT_LOOP,
-            expr.span,
+            arg.span,
             "you are iterating over `Iterator::next()` which is an Option; this will compile but is \
             probably not what you want",
         );
index 2860cb68f42f2c5bc74a371aa2a68ef2fb78209d..5df1b79640164302d2a8532175486208942569e4 100644 (file)
@@ -616,15 +616,15 @@ fn check_for_loop<'tcx>(
         needless_range_loop::check(cx, pat, arg, body, expr);
         explicit_counter_loop::check(cx, pat, arg, body, expr);
     }
-    check_for_loop_arg(cx, pat, arg, expr);
-    for_kv_map::check(cx, pat, arg, body, expr);
+    check_for_loop_arg(cx, pat, arg);
+    for_kv_map::check(cx, pat, arg, body);
     mut_range_bound::check(cx, arg, body);
     single_element_loop::check(cx, pat, arg, body, expr);
     same_item_push::check(cx, pat, arg, body, expr);
     manual_flatten::check(cx, pat, arg, body, span);
 }
 
-fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
+fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 
     if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind {
@@ -637,7 +637,7 @@ fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr:
                 explicit_into_iter_loop::check(cx, self_arg, arg);
             },
             "next" => {
-                next_loop_linted = iter_next_loop::check(cx, arg, expr);
+                next_loop_linted = iter_next_loop::check(cx, arg);
             },
             _ => {},
         }
index e8f3550283a49c85e1411ed9106619dda5e1d8d8..7157b80118558b889cc41556e071dd71891a903e 100644 (file)
@@ -144,7 +144,7 @@ pub(super) fn check<'tcx>(
                     span_lint_and_then(
                         cx,
                         NEEDLESS_RANGE_LOOP,
-                        expr.span,
+                        arg.span,
                         &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
                         |diag| {
                             multispan_sugg(
@@ -170,7 +170,7 @@ pub(super) fn check<'tcx>(
                     span_lint_and_then(
                         cx,
                         NEEDLESS_RANGE_LOOP,
-                        expr.span,
+                        arg.span,
                         &format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed),
                         |diag| {
                             multispan_sugg(
index 7627e0fb28956f3a61a0c8f513d03dad7c29033b..41e6ad12d058923a9af3d1a1b616bd7d650ced23 100644 (file)
     "#[macro_use] is no longer needed"
 }
 
-const BRACKETS: &[char] = &['<', '>'];
-
 #[derive(Clone, Debug, PartialEq, Eq)]
 struct PathAndSpan {
     path: String,
     span: Span,
 }
 
-/// `MacroRefData` includes the name of the macro
-/// and the path from `SourceMap::span_to_filename`.
+/// `MacroRefData` includes the name of the macro.
 #[derive(Debug, Clone)]
 pub struct MacroRefData {
     name: String,
-    path: String,
 }
 
 impl MacroRefData {
-    pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self {
-        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>
-        // so remove brackets, space and type.
-        if path.contains('<') {
-            path = path.replace(BRACKETS, "");
-        }
-        if path.contains(' ') {
-            path = path.split(' ').next().unwrap().to_string();
-        }
-        Self { name, path }
+    pub fn new(name: String) -> Self {
+        Self { name }
     }
 }
 
@@ -78,7 +63,7 @@ impl MacroUseImports {
     fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) {
         let call_site = span.source_callsite();
         let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
-        if let Some(callee) = span.source_callee() {
+        if let Some(_callee) = span.source_callee() {
             if !self.collected.contains(&call_site) {
                 let name = if name.contains("::") {
                     name.split("::").last().unwrap().to_string()
@@ -86,7 +71,7 @@ fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) {
                     name.to_string()
                 };
 
-                self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx));
+                self.mac_refs.push(MacroRefData::new(name));
                 self.collected.insert(call_site);
             }
         }
@@ -95,10 +80,10 @@ fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) {
     fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_>, span: Span) {
         let call_site = span.source_callsite();
         let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
-        if let Some(callee) = span.source_callee() {
+        if let Some(_callee) = span.source_callee() {
             if !self.collected.contains(&call_site) {
                 self.mac_refs
-                    .push(MacroRefData::new(name.to_string(), callee.def_site, cx));
+                    .push(MacroRefData::new(name.to_string()));
                 self.collected.insert(call_site);
             }
         }
index e273186d0519022d5a7c1a9219cf1aa9625fd4a7..001676503242b50b3b7e01b69ebb75896646afac 100644 (file)
@@ -182,7 +182,7 @@ fn parse_iter_usage(
                 },
                 _,
             ) => {
-                let parent_span = e.span.parent().unwrap();
+                let parent_span = e.span.parent_callsite().unwrap();
                 if parent_span.ctxt() == ctxt {
                     (Some(UnwrapKind::QuestionMark), parent_span)
                 } else {
index 80a930d0c547b368460ba8e0e965261b1f7da7d9..f351d0098b7509cf6abdddfef53c21a29cc7a663 100644 (file)
@@ -120,7 +120,7 @@ fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
                     correct.push("mod.rs");
                     cx.struct_span_lint(
                         SELF_NAMED_MODULE_FILES,
-                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
                         |build| {
                             let mut lint =
                                 build.build(&format!("`mod.rs` files are required, found `{}`", path.display()));
@@ -167,7 +167,7 @@ fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &Source
 
         cx.struct_span_lint(
             MOD_MODULE_FILES,
-            Span::new(file.start_pos, file.start_pos, SyntaxContext::root()),
+            Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
             |build| {
                 let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display()));
                 lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),));
index eab097337306be0e8090451909adff8152effe35..947c25ac880565cb946c4872e40e95641e2e293c 100644 (file)
@@ -3,8 +3,7 @@
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{LitKind, StrStyle};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::{BorrowKind, Expr, ExprKind, HirId};
+use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::{BytePos, Span};
 }
 
 #[derive(Clone, Default)]
-pub struct Regex {
-    spans: FxHashSet<Span>,
-    last: Option<HirId>,
-}
+pub struct Regex {}
 
 impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
 
@@ -91,7 +87,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span {
     let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
     let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
     assert!(start <= end);
-    Span::new(start, end, base.ctxt())
+    Span::new(start, end, base.ctxt(), base.parent())
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
index 6a73b94d87e488ec6feaaa24f2d0119a637438a9..4a67cabf323a6a1489f84d485bce350acc98a8cf 100644 (file)
@@ -69,6 +69,7 @@ fn warn_if_tabs_in_doc(cx: &EarlyContext<'_>, attr: &ast::Attribute) {
                     attr.span.lo() + BytePos(3 + lo),
                     attr.span.lo() + BytePos(3 + hi),
                     attr.span.ctxt(),
+                    attr.span.parent(),
                 );
                 span_lint_and_sugg(
                     cx,
index 4c038a997952aba3ff2fd6a14384e17d077badba..7c24e830e71dc406e2c081b77dcc09a47eb08d57 100644 (file)
@@ -5,8 +5,8 @@ edition = "2018"
 publish = false
 
 [dependencies]
-if_chain = "1.0.0"
-rustc-semver="1.1.0"
+if_chain = "1.0"
+rustc-semver = "1.1"
 
 [features]
 deny-warnings = []
index 05a4a0143195080328d5d06788bb9d1bd75ffdc8..94b3cd371bd08ab0113eb96fd24255c9d43b6945 100644 (file)
@@ -105,8 +105,7 @@ pub fn hir(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option<Self> {
             if_else,
         ) = expr.kind
         {
-            let hir = cx.tcx.hir();
-            let mut iter = hir.parent_iter(expr.hir_id);
+            let mut iter = cx.tcx.hir().parent_iter(expr.hir_id);
             if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
                 if let Some((
                     _,
index da259511fe0b927c94ecbce6de5105ecd249ca2a..7f5a1bf9c0741707f0e4e34a66cb0fb6a6e199d7 100644 (file)
@@ -520,7 +520,7 @@ macro_rules! try_res {
             }
         };
     }
-    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
+    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
         tcx.item_children(def_id)
             .iter()
             .find(|item| item.ident.name.as_str() == name)
@@ -557,7 +557,7 @@ fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Opt
                 None
             }
         });
-    try_res!(last).res
+    try_res!(last).res.expect_non_local()
 }
 
 /// Convenience function to get the `DefId` of a trait by path.
@@ -833,12 +833,11 @@ fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
         ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
     ));
 
-    let map = cx.tcx.hir();
     let mut child_id = e.hir_id;
     let mut capture = CaptureKind::Value;
     let mut capture_expr_ty = e;
 
-    for (parent_id, parent) in map.parent_iter(e.hir_id) {
+    for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
         if let [Adjustment {
             kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
             target,
@@ -1224,8 +1223,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
 
 /// Gets the loop or closure enclosing the given expression, if any.
 pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    let map = tcx.hir();
-    for (_, node) in map.parent_iter(expr.hir_id) {
+    for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
         match node {
             Node::Expr(
                 e
@@ -1244,8 +1242,7 @@ pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Opti
 
 /// Gets the parent node if it's an impl block.
 pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
-    let map = tcx.hir();
-    match map.parent_iter(id).next() {
+    match tcx.hir().parent_iter(id).next() {
         Some((
             _,
             Node::Item(Item {
@@ -1259,8 +1256,7 @@ pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
 
 /// Checks if the given expression is the else clause of either an `if` or `if let` expression.
 pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
-    let map = tcx.hir();
-    let mut iter = map.parent_iter(expr.hir_id);
+    let mut iter = tcx.hir().parent_iter(expr.hir_id);
     match iter.next() {
         Some((
             _,
@@ -1794,9 +1790,8 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool {
 
 /// Gets the node where an expression is either used, or it's type is unified with another branch.
 pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
-    let map = tcx.hir();
     let mut child_id = expr.hir_id;
-    let mut iter = map.parent_iter(child_id);
+    let mut iter = tcx.hir().parent_iter(child_id);
     loop {
         match iter.next() {
             None => break None,
index d7e46c2d3eb9d2826966f19fc3d8f98b058a150d..80be4350c3c1a5027bba117e3d78ad09e4d4f9c5 100644 (file)
 pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
-pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs", "PermissionsExt", "from_mode"];
+pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
 pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
 pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
index 8f14b590d27455cbc1fc334e2b80313fab579601..e9a9895cb746f39a6abece6de0aa7df4aa26ca92 100644 (file)
@@ -192,7 +192,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
+        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
         Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
index ada033de6e3abe08ea16c946228514b4f95298ff..f33f1b65eabdba1a45c3859f9ea941c18cd7bf4e 100644 (file)
@@ -11,15 +11,15 @@ publish = false
 
 [dependencies]
 clap = "2.33"
-flate2 = {version = "1.0.19"}
-fs_extra = {version = "1.2.0"}
-rayon = {version = "1.5.0"}
-serde = {version = "1.0", features = ["derive"]}
-serde_json = {version = "1.0"}
-tar = {version = "0.4.30"}
-toml = {version = "0.5"}
-ureq = {version = "2.0.0-rc3"}
-walkdir = {version = "2.3.2"}
+flate2 = "1.0"
+fs_extra = "1.2"
+rayon = "1.5"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+tar = "0.4"
+toml = "0.5"
+ureq = "2.2"
+walkdir = "2.3"
 
 [features]
 deny-warnings = []
index 4c80cabc72305df9371c2854536d7195c7157279..f1f9c123dc842880683a14584d5c63f7bb7aa9c1 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
 #![deny(clippy::default_trait_access)]
 
 use std::default;
index a68b6455c04165f683f4678aae1978a876b4725f..7f3dfc7f01366e0d39b23d59350a2428fe6b0e7c 100644 (file)
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
 #![deny(clippy::default_trait_access)]
 
 use std::default;
index d6aa3fd2631f5caf1412aa6712b5117569627786..e9426a2d9f58ce6a1ab82baae270a040c4422295 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "compiletest"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 colored = "2"
index 37164c4e5752a26aeb2e837a95a74c077d1b9bed..75d392951eca77e9fe73a16fa58d6c0e0798d24a 100644 (file)
@@ -54,6 +54,7 @@
     ("i386", "x86"),
     ("i586", "x86"),
     ("i686", "x86"),
+    ("m68k", "m68k"),
     ("mips", "mips"),
     ("mips64", "mips64"),
     ("mips64el", "mips64"),
index 2e4b7beb3760154857a6441c1c9f86b780b199d1..c84b79e11e9b4ddb578f3653f31d21e660a27709 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "error_index_generator"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 rustdoc = { path = "../../librustdoc" }
index 358dff0653292ea487261e019dcd394fb259ac31..9a25b6c1f1c87e2eb77e90f64074bc8c00060825 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "expand-yaml-anchors"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 yaml-rust = "0.4.3"
index e88d2f0d928fb4c153b3cecaf7bf11ef05237991..34d3954db28dc6b5b1836889db6a35cc30c1fd16 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "html-checker"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [[bin]]
 name = "html-checker"
index a65deb1254168562eca1d32142c25549efa30c6a..ccabe6483d7a41cd4941949dc09e564edc5b4db9 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "jsondocck"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 jsonpath_lib = "0.2"
index 21ba22695564654cb6ff92f1b5a5b7f213e56b80..1d8f2f918823fc01876a2e559f1b59be8e7edb83 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "linkchecker"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [[bin]]
 name = "linkchecker"
index 8cbe0a0c2e8e1736329b4033775ede5a4b8e0f01..94ebbb33e8d8ffad075cd6d06d3248e13e5ecf48 100644 (file)
@@ -30,6 +30,7 @@
 // If at all possible you should use intra-doc links to avoid linkcheck issues. These
 // are cases where that does not work
 // [(generated_documentation_page, &[broken_links])]
+#[rustfmt::skip]
 const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
     // These try to link to std::collections, but are defined in alloc
     // https://github.com/rust-lang/rust/issues/74481
     ("std/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
     ("alloc/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]),
     ("alloc/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
+
+    // These try to link to various things in std, but are defined in core.
+    // The docs in std::primitive use proper intra-doc links, so these seem fine to special-case.
+    // Most these are broken because liballoc uses `#[lang_item]` magic to define things on
+    // primitives that aren't available in core.
+    ("alloc/slice/trait.Join.html", &["#method.join"]),
+    ("alloc/slice/trait.Concat.html", &["#method.concat"]),
+    ("alloc/slice/index.html", &["#method.concat", "#method.join"]),
+    ("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]),
+    ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]),
+    ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
+                                    "core/slice::sort_by_key", "core\\slice::sort_by_key",
+                                    "#method.sort_by_cached_key"]),
 ];
 
 #[rustfmt::skip]
@@ -376,6 +390,10 @@ fn check(&mut self, file: &Path, report: &mut Report) {
 
     /// Load a file from disk, or from the cache if available.
     fn load_file(&mut self, file: &Path, report: &mut Report) -> (String, &FileEntry) {
+        // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+        #[cfg(windows)]
+        const ERROR_INVALID_NAME: i32 = 123;
+
         let pretty_path =
             file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
 
@@ -392,6 +410,14 @@ fn load_file(&mut self, file: &Path, report: &mut Report) -> (String, &FileEntry
                 }
                 Err(e) if e.kind() == ErrorKind::NotFound => FileEntry::Missing,
                 Err(e) => {
+                    // If a broken intra-doc link contains `::`, on windows, it will cause `ERROR_INVALID_NAME` rather than `NotFound`.
+                    // Explicitly check for that so that the broken link can be allowed in `LINKCHECK_EXCEPTIONS`.
+                    #[cfg(windows)]
+                    if e.raw_os_error() == Some(ERROR_INVALID_NAME)
+                        && file.as_os_str().to_str().map_or(false, |s| s.contains("::"))
+                    {
+                        return FileEntry::Missing;
+                    }
                     panic!("unexpected read error for {}: {}", file.display(), e);
                 }
             });
index 6792887fa5d718f31ec265ae53b4c495d0920a8a..3578bda8276e76e2dfe3ea4d2d7e0a07394acfb0 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "lint-docs"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 description = "A script to extract the lint documentation for the rustc book."
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
index e5c7f1257123801d48a39812cfb003967342ee6d..fdc89a184da527ba7bb44fc28b552eb1390a46ce 100644 (file)
@@ -149,6 +149,10 @@ fn lints_from_file(&self, path: &Path) -> Result<Vec<Lint>, Box<dyn Error>> {
                         } else if line.starts_with("// ") {
                             // Ignore comments.
                             continue;
+                        } else if line.starts_with("#[allow") {
+                            // Ignore allow of lints (useful for
+                            // invalid_rust_codeblocks).
+                            continue;
                         } else {
                             let name = lint_name(line).map_err(|e| {
                                 format!(
index 7a2f1cadcd5120c44eda3596053de767cd8173a2..035933186957cf81c488261fb48a98bf523e8006 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7a2f1cadcd5120c44eda3596053de767cd8173a2
+Subproject commit 035933186957cf81c488261fb48a98bf523e8006
index f97914b1e97561f40e4a70dc18be66b29da1dff9..04a1d257bc094e317e036da965987159ee5be842 100755 (executable)
@@ -299,7 +299,13 @@ try:
     if repo:
         github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
         if github_token:
-            validate_maintainers(repo, github_token)
+            # FIXME: This is currently broken. Starting on 2021-09-15, GitHub
+            # seems to have changed it so that to list the collaborators
+            # requires admin permissions. I think this will probably just need
+            # to be removed since we are probably not going to use an admin
+            # token, and I don't see another way to do this.
+            print('maintainer validation disabled')
+            # validate_maintainers(repo, github_token)
         else:
             print('skipping toolstate maintainers validation since no GitHub token is present')
         # When validating maintainers don't run the full script.
index 7b20ba83546be38031e61c062f479e94e058c9fd..d59cd6b3d8e225834c3444d91ed29a277bf62bb4 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "remote-test-client"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
index 01309aec9a33895ec50d663dec2db95fdfd4ef9d..e6be8530cf635ad18f23b026a32846755a42f123 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "remote-test-server"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
index b73b321478d3b2a98d380eb79de717e01620c4e9..f1d7f98ed07b9934286b9c4809dd4d7a47537879 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
+Subproject commit f1d7f98ed07b9934286b9c4809dd4d7a47537879
index 157409bc8472c80200debddf3eb61f82bba9c8e9..2bb73b3262d8d7bde3509446893af75f20c3d938 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rust-demangler"
 version = "0.0.1"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 regex = "1.0"
index da36ce0e69002442d5bafd6c910af73770bfad8f..de1327d74ff57f8d567b9dac4259dca434d52f57 100644 (file)
@@ -2,7 +2,7 @@
 name = "rustbook"
 version = "0.1.0"
 license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 clap = "2.25.0"
index 38b9fefbaf576ee11205af5e92eea6a6dd73b692..a28cf28841e54de042dba7cf874af3983bb01fbb 100644 (file)
@@ -5,7 +5,7 @@ license = 'MIT OR Apache-2.0'
 description = """
 Hack for the compiler's own build system
 """
-edition = "2018"
+edition = "2021"
 
 [lib]
 path = "lib.rs"
index 4b2ad982a84fb2d81b2bce8f34e030e5d0cae24f..3d8c77d36d70dd965fcb5419aa2c08e4defe1624 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc-themes"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 [[bin]]
 name = "rustdoc-themes"
index 5625707b25a5323d82726e3019b1c9fb3faacc54..c4101f72cc2da64fe6faf3a17298f1e1806d091a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc-tool"
 version = "0.0.0"
-edition = "2018"
+edition = "2021"
 
 # Cargo adds a number of paths to the dylib search path on windows, which results in
 # the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
index 81e3e26e8b000db67ace239c2e45fd475d1d727d..7b4667c17c8647cd3e6f7ddacf33a077df20b531 100644 (file)
@@ -8,7 +8,7 @@ readme = "README.md"
 license = "Apache-2.0/MIT"
 build = "build.rs"
 categories = ["development-tools"]
-edition = "2018"
+edition = "2021"
 
 [[bin]]
 name = "rustfmt"
index 2483d0570d9eaf1c27358646918b8bd56c50bfcb..14041539b9dfd618536dc240416b65a60f283d3d 100644 (file)
@@ -6,7 +6,7 @@
 use regex::Regex;
 use rustc_ast::visit;
 use rustc_ast::{ast, ptr};
-use rustc_span::{symbol, BytePos, Span};
+use rustc_span::{symbol, BytePos, Span, DUMMY_SP};
 
 use crate::attr::filter_inline_attrs;
 use crate::comment::{
 use crate::utils::*;
 use crate::vertical::rewrite_with_alignment;
 use crate::visitor::FmtVisitor;
-use crate::DEFAULT_VISIBILITY;
+
+const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
+    kind: ast::VisibilityKind::Inherited,
+    span: DUMMY_SP,
+    tokens: None,
+};
 
 fn type_annotation_separator(config: &Config) -> &str {
     colon_spaces(config)
@@ -972,7 +977,7 @@ fn format_header(&self, context: &RewriteContext<'_>, offset: Indent) -> String
         format_header(context, self.prefix, self.ident, self.vis, offset)
     }
 
-    pub(crate) fn from_variant(variant: &'a ast::Variant) -> Self {
+    fn from_variant(variant: &'a ast::Variant) -> Self {
         StructParts {
             prefix: "",
             ident: variant.ident,
index 206d2f782909c9f0639398ce75044b7509ffdc49..47a7b9d4dbe3cb80baa2d08d979e9e94e2b56241 100644 (file)
@@ -32,7 +32,7 @@
 use std::rc::Rc;
 
 use rustc_ast::ast;
-use rustc_span::{symbol, DUMMY_SP};
+use rustc_span::symbol;
 use thiserror::Error;
 
 use crate::comment::LineClasses;
 mod vertical;
 pub(crate) mod visitor;
 
-const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
-    kind: ast::VisibilityKind::Inherited,
-    span: DUMMY_SP,
-    tokens: None,
-};
 /// The various errors that can occur during formatting. Note that not all of
 /// these can currently be propagated to clients.
 #[derive(Error, Debug)]
index a9bc89544d820cd5c0b592fdc9ee4d74c0057ff3..927187dfd8a2336b20220dd9e794bc04171f0eff 100644 (file)
@@ -762,7 +762,6 @@ fn rewrite(
 #[derive(Debug, Clone)]
 struct ParsedMacroArg {
     kind: MacroArgKind,
-    span: Span,
 }
 
 impl ParsedMacroArg {
@@ -780,14 +779,10 @@ fn rewrite(
 struct MacroArgParser {
     /// Either a name of the next metavariable, a separator, or junk.
     buf: String,
-    /// The start position on the current buffer.
-    lo: BytePos,
     /// The first token of the current buffer.
     start_tok: Token,
     /// `true` if we are parsing a metavariable or a repeat.
     is_meta_var: bool,
-    /// The position of the last token.
-    hi: BytePos,
     /// The last token parsed.
     last_tok: Token,
     /// Holds the parsed arguments.
@@ -807,8 +802,6 @@ fn last_tok(tt: &TokenTree) -> Token {
 impl MacroArgParser {
     fn new() -> MacroArgParser {
         MacroArgParser {
-            lo: BytePos(0),
-            hi: BytePos(0),
             buf: String::new(),
             is_meta_var: false,
             last_tok: Token {
@@ -824,7 +817,6 @@ fn new() -> MacroArgParser {
     }
 
     fn set_last_tok(&mut self, tok: &TokenTree) {
-        self.hi = tok.span().hi();
         self.last_tok = last_tok(tok);
     }
 
@@ -836,7 +828,6 @@ fn add_separator(&mut self) {
         };
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Separator(self.buf.clone(), prefix),
-            span: mk_sp(self.lo, self.hi),
         });
         self.buf.clear();
     }
@@ -849,7 +840,6 @@ fn add_other(&mut self) {
         };
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Other(self.buf.clone(), prefix),
-            span: mk_sp(self.lo, self.hi),
         });
         self.buf.clear();
     }
@@ -858,11 +848,10 @@ fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
         match iter.next() {
             Some(TokenTree::Token(Token {
                 kind: TokenKind::Ident(name, _),
-                span,
+                ..
             })) => {
                 self.result.push(ParsedMacroArg {
                     kind: MacroArgKind::MetaVariable(name, self.buf.clone()),
-                    span: mk_sp(self.lo, span.hi()),
                 });
 
                 self.buf.clear();
@@ -873,10 +862,9 @@ fn add_meta_variable(&mut self, iter: &mut Cursor) -> Option<()> {
         }
     }
 
-    fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken, span: Span) {
+    fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken) {
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Delimited(delim, inner),
-            span,
         });
     }
 
@@ -886,19 +874,15 @@ fn add_repeat(
         inner: Vec<ParsedMacroArg>,
         delim: DelimToken,
         iter: &mut Cursor,
-        span: Span,
     ) -> Option<()> {
         let mut buffer = String::new();
         let mut first = true;
-        let mut lo = span.lo();
-        let mut hi = span.hi();
 
         // Parse '*', '+' or '?.
         for tok in iter {
             self.set_last_tok(&tok);
             if first {
                 first = false;
-                lo = tok.span().lo();
             }
 
             match tok {
@@ -918,7 +902,6 @@ fn add_repeat(
                 }
                 TokenTree::Token(ref t) => {
                     buffer.push_str(&pprust::token_to_string(&t));
-                    hi = t.span.hi();
                 }
                 _ => return None,
             }
@@ -930,20 +913,17 @@ fn add_repeat(
         } else {
             Some(Box::new(ParsedMacroArg {
                 kind: MacroArgKind::Other(buffer, "".to_owned()),
-                span: mk_sp(lo, hi),
             }))
         };
 
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()),
-            span: mk_sp(self.lo, self.hi),
         });
         Some(())
     }
 
     fn update_buffer(&mut self, t: &Token) {
         if self.buf.is_empty() {
-            self.lo = t.span.lo();
             self.start_tok = t.clone();
         } else {
             let needs_space = match next_space(&self.last_tok.kind) {
@@ -999,7 +979,6 @@ fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
 
                     // Start keeping the name of this metavariable in the buffer.
                     self.is_meta_var = true;
-                    self.lo = span.lo();
                     self.start_tok = Token {
                         kind: TokenKind::Dollar,
                         span,
@@ -1012,7 +991,7 @@ fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
                     self.add_meta_variable(&mut iter)?;
                 }
                 TokenTree::Token(ref t) => self.update_buffer(t),
-                TokenTree::Delimited(delimited_span, delimited, ref tts) => {
+                TokenTree::Delimited(_delimited_span, delimited, ref tts) => {
                     if !self.buf.is_empty() {
                         if next_space(&self.last_tok.kind) == SpaceState::Always {
                             self.add_separator();
@@ -1022,16 +1001,14 @@ fn parse(mut self, tokens: TokenStream) -> Option<Vec<ParsedMacroArg>> {
                     }
 
                     // Parse the stuff inside delimiters.
-                    let mut parser = MacroArgParser::new();
-                    parser.lo = delimited_span.open.lo();
+                    let parser = MacroArgParser::new();
                     let delimited_arg = parser.parse(tts.clone())?;
 
-                    let span = delimited_span.entire();
                     if self.is_meta_var {
-                        self.add_repeat(delimited_arg, delimited, &mut iter, span)?;
+                        self.add_repeat(delimited_arg, delimited, &mut iter)?;
                         self.is_meta_var = false;
                     } else {
-                        self.add_delimited(delimited_arg, delimited, span);
+                        self.add_delimited(delimited_arg, delimited);
                     }
                 }
             }
@@ -1270,7 +1247,12 @@ fn parse_branch(&mut self) -> Option<MacroBranch> {
                 let data = delimited_span.entire().data();
                 (
                     data.hi,
-                    Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
+                    Span::new(
+                        data.lo + BytePos(1),
+                        data.hi - BytePos(1),
+                        data.ctxt,
+                        data.parent,
+                    ),
                     delimited_span.entire(),
                 )
             }
index 5de0575b5cd66a56a466466608cdf47b9b8600a9..ded34d9032f91f188c11c9437b41691cdcce75b5 100644 (file)
@@ -27,7 +27,6 @@
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
     pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-    attrs: Cow<'a, Vec<ast::Attribute>>,
     inner_attr: Vec<ast::Attribute>,
     pub(crate) span: Span,
 }
@@ -46,7 +45,6 @@ pub(crate) fn new(
             .collect();
         Module {
             items: mod_items,
-            attrs: mod_attrs,
             inner_attr,
             span: mod_span,
             ast_mod_kind,
index 640d127e8609818052a0024ad2aa8f604b215066..76bf58e875b1f6d48218fce5a909ac010ddd2b40 100644 (file)
@@ -1,15 +1,15 @@
 use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
-use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
-use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
+use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
+use crate::comment::{combine_strs_with_missing_comments, contains_comment};
 use crate::config::lists::*;
 use crate::config::{IndentStyle, TypeDensity, Version};
 use crate::expr::{
     format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
 };
-use crate::items::StructParts;
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
 };
     colon_spaces, extra_offset, first_line_width, format_extern, format_mutability,
     last_line_extendable, last_line_width, mk_sp, rewrite_ident,
 };
-use crate::DEFAULT_VISIBILITY;
-use crate::{
-    comment::{combine_strs_with_missing_comments, contains_comment},
-    items::format_struct_struct,
-};
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub(crate) enum PathContext {
@@ -769,54 +764,6 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
             ast::TyKind::Tup(ref items) => {
                 rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
             }
-            ast::TyKind::AnonymousStruct(ref fields, recovered) => {
-                let ident = Ident::new(
-                    kw::Struct,
-                    mk_sp(self.span.lo(), self.span.lo() + BytePos(6)),
-                );
-                let data = ast::VariantData::Struct(fields.clone(), recovered);
-                let variant = ast::Variant {
-                    attrs: AttrVec::new(),
-                    id: self.id,
-                    span: self.span,
-                    vis: DEFAULT_VISIBILITY,
-                    ident,
-                    data,
-                    disr_expr: None,
-                    is_placeholder: false,
-                };
-                format_struct_struct(
-                    &context,
-                    &StructParts::from_variant(&variant),
-                    fields,
-                    shape.indent,
-                    None,
-                )
-            }
-            ast::TyKind::AnonymousUnion(ref fields, recovered) => {
-                let ident = Ident::new(
-                    kw::Union,
-                    mk_sp(self.span.lo(), self.span.lo() + BytePos(5)),
-                );
-                let data = ast::VariantData::Struct(fields.clone(), recovered);
-                let variant = ast::Variant {
-                    attrs: AttrVec::new(),
-                    id: self.id,
-                    span: self.span,
-                    vis: DEFAULT_VISIBILITY,
-                    ident,
-                    data,
-                    disr_expr: None,
-                    is_placeholder: false,
-                };
-                format_struct_struct(
-                    &context,
-                    &StructParts::from_variant(&variant),
-                    fields,
-                    shape.indent,
-                    None,
-                )
-            }
             ast::TyKind::Path(ref q_self, ref path) => {
                 rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
             }
index 06159a1b26e8698cdf0102b7c95514c7354e8ebc..29e1e070d41114079921683fea87f7cd62ec941f 100644 (file)
@@ -356,11 +356,11 @@ macro_rules! source {
 }
 
 pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
-    Span::new(lo, hi, SyntaxContext::root())
+    Span::new(lo, hi, SyntaxContext::root(), None)
 }
 
 pub(crate) fn mk_sp_lo_plus_one(lo: BytePos) -> Span {
-    Span::new(lo, lo + BytePos(1), SyntaxContext::root())
+    Span::new(lo, lo + BytePos(1), SyntaxContext::root(), None)
 }
 
 // Returns `true` if the given span does not intersect with file lines.
index 57fe5a62e9aa7a629411344b958337f877ae8e07..69c8063f42e26693c441251b65210961d50feb88 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "tidy"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 autobins = false
 
 [dependencies]
index 5f1267fc3d2507db7adfa95f14efffcf1a4b99be..60703384e9e85ab74b6c967c4033fc8987bd4a19 100644 (file)
     "num-integer",
     "num-traits",
     "object",
+    "odht",
     "once_cell",
     "opaque-debug",
     "parking_lot",
index 283c43e325c05422c7003f069005b025d97ad2ab..b5e9ceddbafd166832874a26c34009ae1b363f60 100644 (file)
@@ -1,10 +1,15 @@
-//! Tidy check to ensure that crate `edition` is '2018'
+//! Tidy check to ensure that crate `edition` is '2018' or '2021'.
 
 use std::path::Path;
 
 fn is_edition_2018(mut line: &str) -> bool {
     line = line.trim();
-    line == "edition = \"2018\"" || line == "edition = \'2018\'"
+    line == "edition = \"2018\""
+}
+
+fn is_edition_2021(mut line: &str) -> bool {
+    line = line.trim();
+    line == "edition = \"2021\""
 }
 
 pub fn check(path: &Path, bad: &mut bool) {
@@ -13,17 +18,38 @@ pub fn check(path: &Path, bad: &mut bool) {
         &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
         &mut |entry, contents| {
             let file = entry.path();
+            let filestr = file.to_string_lossy().replace("\\", "/");
             let filename = file.file_name().unwrap();
             if filename != "Cargo.toml" {
                 return;
             }
-            let has_edition = contents.lines().any(is_edition_2018);
-            if !has_edition {
-                tidy_error!(
-                    bad,
-                    "{} doesn't have `edition = \"2018\"` on a separate line",
-                    file.display()
-                );
+
+            // Library crates are not yet ready to migrate to 2021.
+            //
+            // The reference and rustc-dev-guide are submodules, so are left at
+            // 2018 for now. They should be removed from this exception list
+            // when bumped.
+            if path.components().any(|c| c.as_os_str() == "library")
+                || filestr.contains("src/doc/reference/style-check/Cargo.toml")
+                || filestr.contains("src/doc/rustc-dev-guide/ci/date-check/Cargo.toml")
+            {
+                let has = contents.lines().any(is_edition_2018);
+                if !has {
+                    tidy_error!(
+                        bad,
+                        "{} doesn't have `edition = \"2018\"` on a separate line",
+                        file.display()
+                    );
+                }
+            } else {
+                let is_2021 = contents.lines().any(is_edition_2021);
+                if !is_2021 {
+                    tidy_error!(
+                        bad,
+                        "{} doesn't have `edition = \"2021\"` on a separate line",
+                        file.display()
+                    );
+                }
             }
         },
     );
index a1c41eb99810e8c51b247b6b6dcb47f9604fb981..35809e599266c8111e6758f84307b1371838ea69 100644 (file)
@@ -46,6 +46,7 @@ macro_rules! tidy_error {
 pub mod extdeps;
 pub mod features;
 pub mod pal;
+pub mod primitive_docs;
 pub mod style;
 pub mod target_specific_tests;
 pub mod ui_tests;
index 440c352ea5320de9319e91c01525929028e3b96f..d555f7c8e34fffbaefb5158ddc5e2b815bf77ea3 100644 (file)
@@ -71,6 +71,7 @@ macro_rules! check {
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
+        check!(primitive_docs, &library_path);
 
         // Checks that need to be done for both the compiler and std libraries.
         check!(unit_tests, &src_path);
diff --git a/src/tools/tidy/src/primitive_docs.rs b/src/tools/tidy/src/primitive_docs.rs
new file mode 100644 (file)
index 0000000..8476650
--- /dev/null
@@ -0,0 +1,17 @@
+//! Tidy check to make sure `library/{std,core}/src/primitive_docs.rs` are the same file.  These are
+//! different files so that relative links work properly without having to have `CARGO_PKG_NAME`
+//! set, but conceptually they should always be the same.
+
+use std::path::Path;
+
+pub fn check(library_path: &Path, bad: &mut bool) {
+    let std_name = "std/src/primitive_docs.rs";
+    let core_name = "core/src/primitive_docs.rs";
+    let std_contents = std::fs::read_to_string(library_path.join(std_name))
+        .unwrap_or_else(|e| panic!("failed to read library/{}: {}", std_name, e));
+    let core_contents = std::fs::read_to_string(library_path.join(core_name))
+        .unwrap_or_else(|e| panic!("failed to read library/{}: {}", core_name, e));
+    if std_contents != core_contents {
+        tidy_error!(bad, "library/{} and library/{} have different contents", core_name, std_name);
+    }
+}
index 46b5b877b4c26f93b30e56e12b9c949b847c09ee..a341527c84cf065d3b6774cc63b3b21a8a7acf8f 100644 (file)
@@ -7,8 +7,8 @@
 
 const ENTRY_LIMIT: usize = 1000;
 // FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1345;
-const ISSUES_ENTRY_LIMIT: usize = 2525;
+const ROOT_ENTRY_LIMIT: usize = 1330;
+const ISSUES_ENTRY_LIMIT: usize = 2488;
 
 fn check_entries(path: &Path, bad: &mut bool) {
     let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
index d6119cac5f39eb46d314e3a5c2ad787e8ee861ca..3f08165a3fc63350077d0c234a00bb07a4bcd51f 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "tier-check"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 license = "MIT OR Apache-2.0"
 
 [dependencies]
index 948773f7810c3d2c85f560538124cf35f33012b6..ef01877c0b94bcffff9e49148aa7be1a00c84ac8 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "unicode-bdd"
 version = "0.1.0"
-edition = "2018"
+edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
index febeaa446b39411e574dc80868e166177f706ee1..73e5a91bec70a358917ff9ddf99e4c21de25cc3c 100644 (file)
@@ -2,7 +2,7 @@
 name = "unstable-book-gen"
 version = "0.1.0"
 license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
 
 [dependencies]
 tidy = { path = "../tidy" }
index 264a741159a8acb7a475eb382ba41ba76f864029..315027279623411f8af85ed53c86550c79556d70 100644 (file)
@@ -2,5 +2,5 @@
 name = "x"
 version = "0.1.0"
 description = "Run x.py slightly more conveniently"
-edition = "2018"
+edition = "2021"
 publish = false